Reorganizes Project (#41)

This commit is contained in:
Kamron Batman 2019-08-02 18:13:40 -07:00 committed by GitHub
parent 08bf44af9a
commit 3614a66aee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3499 changed files with 79 additions and 55 deletions

View file

@ -0,0 +1,28 @@
using Server.Targeting;
namespace Server.Engines.BulkOrders
{
public class BODTarget : Target
{
private BaseBOD m_Deed;
public BODTarget(BaseBOD deed) : base(18, false, TargetFlags.None)
{
m_Deed = deed;
}
protected override void OnTarget(Mobile from, object targeted)
{
if (m_Deed.Deleted || !m_Deed.IsChildOf(from.Backpack))
return;
if (!(targeted is Item item && item.IsChildOf(from.Backpack)))
{
from.SendLocalizedMessage( 1045158 ); // You must have the item in your backpack to target it.
return;
}
m_Deed.EndCombine(from, item);
}
}
}

View file

@ -0,0 +1,153 @@
using System.Collections.Generic;
namespace Server.Engines.BulkOrders
{
public abstract class BaseBOD : Item
{
private int m_AmountMax;
private bool m_RequireExceptional;
private BulkMaterialType m_Material;
public static BulkMaterialType GetRandomMaterial(BulkMaterialType start, double[] chances)
{
double random = Utility.RandomDouble();
for ( int i = 0; i < chances.Length; ++i )
{
if ( random < chances[i] )
return i == 0 ? BulkMaterialType.None : start + (i - 1);
random -= chances[i];
}
return BulkMaterialType.None;
}
public BaseBOD(int hue, int amountMax, bool requireExeptional, BulkMaterialType material) : this()
{
Hue = hue;
AmountMax = amountMax;
RequireExceptional = requireExeptional;
Material = material;
}
public BaseBOD() : base(Core.AOS ? 0x2258 : 0x14EF)
{
Weight = 1.0;
LootType = LootType.Blessed;
}
public BaseBOD(Serial serial) : base(serial)
{
}
public abstract bool Complete{ get; }
[CommandProperty(AccessLevel.GameMaster)]
public sealed override int Hue{ get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int AmountMax
{
get => m_AmountMax;
set{ m_AmountMax = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public bool RequireExceptional
{
get => m_RequireExceptional;
set{ m_RequireExceptional = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public BulkMaterialType Material
{
get => m_Material;
set{ m_Material = value; InvalidateProperties(); }
}
public abstract RewardGroup GetRewardGroup();
public abstract int ComputeGold();
public abstract int ComputeFame();
public abstract void EndCombine(Mobile from, Item item);
public virtual void GetRewards(out Item reward, out int gold, out int fame)
{
gold = ComputeGold();
fame = ComputeFame();
List<RewardItem> rewards = ComputeRewards(false);
reward = rewards.Count <= 0 ? null : rewards[Utility.Random(rewards.Count)].Construct();
}
public virtual List<RewardItem> ComputeRewards(bool full)
{
RewardGroup rewardGroup = GetRewardGroup();
List<RewardItem> list = new List<RewardItem>();
if (full)
{
for (int i = 0; i < rewardGroup?.Items.Length; ++i)
{
RewardItem reward = rewardGroup.Items[i];
if (reward != null)
list.Add(reward);
}
}
else
{
RewardItem reward = rewardGroup.AcquireItem();
if (reward != null)
list.Add(reward);
}
return list;
}
public virtual void BeginCombine(Mobile from)
{
if (Complete)
from.SendLocalizedMessage(1045166); // The maximum amount of requested items have already been combined to this deed.
else
from.Target = new BODTarget(this);
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( 0 ); // version
writer.Write( m_AmountMax );
writer.Write( m_RequireExceptional );
writer.Write( (int) m_Material );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
switch ( version )
{
case 0:
{
m_AmountMax = reader.ReadInt();
m_RequireExceptional = reader.ReadBool();
m_Material = (BulkMaterialType)reader.ReadInt();
break;
}
}
if ( Parent == null && Map == Map.Internal && Location == Point3D.Zero )
Delete();
}
}
}

View file

@ -0,0 +1,62 @@
namespace Server.Engines.BulkOrders
{
public class BOBFilter
{
public BOBFilter()
{
}
public BOBFilter(GenericReader reader)
{
int version = reader.ReadEncodedInt();
switch (version)
{
case 1:
{
Type = reader.ReadEncodedInt();
Quality = reader.ReadEncodedInt();
Material = reader.ReadEncodedInt();
Quantity = reader.ReadEncodedInt();
break;
}
}
}
public bool IsDefault => Type == 0 && Quality == 0 && Material == 0 && Quantity == 0;
public int Type{ get; set; }
public int Quality{ get; set; }
public int Material{ get; set; }
public int Quantity{ get; set; }
public void Clear()
{
Type = 0;
Quality = 0;
Material = 0;
Quantity = 0;
}
public void Serialize(GenericWriter writer)
{
if (IsDefault)
{
writer.WriteEncodedInt(0); // version
}
else
{
writer.WriteEncodedInt(1); // version
writer.WriteEncodedInt(Type);
writer.WriteEncodedInt(Quality);
writer.WriteEncodedInt(Material);
writer.WriteEncodedInt(Quantity);
}
}
}
}

View file

@ -0,0 +1,220 @@
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.BulkOrders
{
public class BOBFilterGump : Gump
{
private const int LabelColor = 0x7FFF;
private static int[,] m_MaterialFilters =
{
{ 1044067, 1 }, // Blacksmithy
{ 1062226, 3 }, // Iron
{ 1018332, 4 }, // Dull Copper
{ 1018333, 5 }, // Shadow Iron
{ 1018334, 6 }, // Copper
{ 1018335, 7 }, // Bronze
{ 0, 0 }, // --Blank--
{ 1018336, 8 }, // Golden
{ 1018337, 9 }, // Agapite
{ 1018338, 10 }, // Verite
{ 1018339, 11 }, // Valorite
{ 0, 0 }, // --Blank--
{ 1044094, 2 }, // Tailoring
{ 1044286, 12 }, // Cloth
{ 1062235, 13 }, // Leather
{ 1062236, 14 }, // Spined
{ 1062237, 15 }, // Horned
{ 1062238, 16 } // Barbed
};
private static int[,] m_TypeFilters =
{
{ 1062229, 0 }, // All
{ 1062224, 1 }, // Small
{ 1062225, 2 } // Large
};
private static int[,] m_QualityFilters =
{
{ 1062229, 0 }, // All
{ 1011542, 1 }, // Normal
{ 1060636, 2 } // Exceptional
};
private static int[,] m_AmountFilters =
{
{ 1062229, 0 }, // All
{ 1049706, 1 }, // 10
{ 1016007, 2 }, // 15
{ 1062239, 3 } // 20
};
private static int[][,] m_Filters =
{
m_TypeFilters,
m_QualityFilters,
m_MaterialFilters,
m_AmountFilters
};
private static int[] m_XOffsets_Type = { 0, 75, 170 };
private static int[] m_XOffsets_Quality = { 0, 75, 170 };
private static int[] m_XOffsets_Amount = { 0, 75, 180, 275 };
private static int[] m_XOffsets_Material = { 0, 105, 210, 305, 390, 485 };
private static int[] m_XWidths_Small = { 50, 50, 70, 50 };
private static int[] m_XWidths_Large = { 80, 50, 50, 50, 50, 50 };
private BulkOrderBook m_Book;
private PlayerMobile m_From;
public BOBFilterGump(PlayerMobile from, BulkOrderBook book) : base(12, 24)
{
from.CloseGump<BOBGump>();
from.CloseGump<BOBFilterGump>();
m_From = from;
m_Book = book;
BOBFilter f = from.UseOwnFilter ? from.BOBFilter : book.Filter;
AddPage(0);
AddBackground(10, 10, 600, 439, 5054);
AddImageTiled(18, 20, 583, 420, 2624);
AddAlphaRegion(18, 20, 583, 420);
AddImage(5, 5, 10460);
AddImage(585, 5, 10460);
AddImage(5, 424, 10460);
AddImage(585, 424, 10460);
AddHtmlLocalized(270, 32, 200, 32, 1062223, LabelColor); // Filter Preference
AddHtmlLocalized(26, 64, 120, 32, 1062228, LabelColor); // Bulk Order Type
AddFilterList(25, 96, m_XOffsets_Type, 40, m_TypeFilters, m_XWidths_Small, f.Type, 0);
AddHtmlLocalized(320, 64, 50, 32, 1062215, LabelColor); // Quality
AddFilterList(320, 96, m_XOffsets_Quality, 40, m_QualityFilters, m_XWidths_Small, f.Quality, 1);
AddHtmlLocalized(26, 160, 120, 32, 1062232, LabelColor); // Material Type
AddFilterList(25, 192, m_XOffsets_Material, 40, m_MaterialFilters, m_XWidths_Large, f.Material, 2);
AddHtmlLocalized(26, 320, 120, 32, 1062217, LabelColor); // Amount
AddFilterList(25, 352, m_XOffsets_Amount, 40, m_AmountFilters, m_XWidths_Small, f.Quantity, 3);
AddHtmlLocalized(75, 416, 120, 32, 1062477, from.UseOwnFilter ? LabelColor : 16927); // Set Book Filter
AddButton(40, 416, 4005, 4007, 1);
AddHtmlLocalized(235, 416, 120, 32, 1062478, from.UseOwnFilter ? 16927 : LabelColor); // Set Your Filter
AddButton(200, 416, 4005, 4007, 2);
AddHtmlLocalized(405, 416, 120, 32, 1062231, LabelColor); // Clear Filter
AddButton(370, 416, 4005, 4007, 3);
AddHtmlLocalized(540, 416, 50, 32, 1011046, LabelColor); // APPLY
AddButton(505, 416, 4017, 4018, 0);
}
private void AddFilterList(int x, int y, int[] xOffsets, int yOffset, int[,] filters, int[] xWidths, int filterValue,
int filterIndex)
{
for (int i = 0; i < filters.GetLength(0); ++i)
{
int number = filters[i, 0];
if (number == 0)
continue;
bool isSelected = filters[i, 1] == filterValue ||
i % xOffsets.Length == 0 && filterValue == 0;
AddHtmlLocalized(x + 35 + xOffsets[i % xOffsets.Length], y + i / xOffsets.Length * yOffset,
xWidths[i % xOffsets.Length], 32, number, isSelected ? 16927 : LabelColor);
AddButton(x + xOffsets[i % xOffsets.Length], y + i / xOffsets.Length * yOffset, 4005, 4007,
4 + filterIndex + i * 4);
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
BOBFilter f = m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter;
int index = info.ButtonID;
switch (index)
{
case 0: // Apply
{
m_From.SendGump(new BOBGump(m_From, m_Book));
break;
}
case 1: // Set Book Filter
{
m_From.UseOwnFilter = false;
m_From.SendGump(new BOBFilterGump(m_From, m_Book));
break;
}
case 2: // Set Your Filter
{
m_From.UseOwnFilter = true;
m_From.SendGump(new BOBFilterGump(m_From, m_Book));
break;
}
case 3: // Clear Filter
{
f.Clear();
m_From.SendGump(new BOBFilterGump(m_From, m_Book));
break;
}
default:
{
index -= 4;
int type = index % 4;
index /= 4;
if (type >= 0 && type < m_Filters.Length)
{
int[,] filters = m_Filters[type];
if (index >= 0 && index < filters.GetLength(0))
{
if (filters[index, 0] == 0)
break;
switch (type)
{
case 0:
f.Type = filters[index, 1];
break;
case 1:
f.Quality = filters[index, 1];
break;
case 2:
f.Material = filters[index, 1];
break;
case 3:
f.Quantity = filters[index, 1];
break;
}
m_From.SendGump(new BOBFilterGump(m_From, m_Book));
}
}
break;
}
}
}
}
}

View file

@ -0,0 +1,647 @@
using System;
using System.Collections.Generic;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Network;
using Server.Prompts;
namespace Server.Engines.BulkOrders
{
public class BOBGump : Gump
{
private const int LabelColor = 0x7FFF;
private BulkOrderBook m_Book;
private PlayerMobile m_From;
private List<IBOBEntry> m_List;
private int m_Page;
public BOBGump(PlayerMobile from, BulkOrderBook book, int page = 0, List<IBOBEntry> list = null) : base(12, 24)
{
from.CloseGump<BOBGump>();
from.CloseGump<BOBFilterGump>();
m_From = from;
m_Book = book;
m_Page = page;
if (list == null)
{
list = new List<IBOBEntry>(book.Entries.Count);
for (int i = 0; i < book.Entries.Count; ++i)
{
IBOBEntry entry = book.Entries[i];
if (CheckFilter(entry))
list.Add(entry);
}
}
m_List = list;
int index = GetIndexForPage(page);
int count = GetCountForIndex(index);
int tableIndex = 0;
PlayerVendor pv = book.RootParent as PlayerVendor;
bool canDrop = book.IsChildOf(from.Backpack);
bool canBuy = pv != null;
bool canPrice = canDrop || canBuy;
if (canBuy)
{
VendorItem vi = pv.GetVendorItem(book);
canBuy = vi?.IsForSale == false;
}
int width = 600;
if (!canPrice)
width = 516;
X = (624 - width) / 2;
AddPage(0);
AddBackground(10, 10, width, 439, 5054);
AddImageTiled(18, 20, width - 17, 420, 2624);
if (canPrice)
{
AddImageTiled(573, 64, 24, 352, 200);
AddImageTiled(493, 64, 78, 352, 1416);
}
if (canDrop)
AddImageTiled(24, 64, 32, 352, 1416);
AddImageTiled(58, 64, 36, 352, 200);
AddImageTiled(96, 64, 133, 352, 1416);
AddImageTiled(231, 64, 80, 352, 200);
AddImageTiled(313, 64, 100, 352, 1416);
AddImageTiled(415, 64, 76, 352, 200);
for (int i = index; i < index + count && i >= 0 && i < list.Count; ++i)
{
IBOBEntry entry = list[i];
if (!CheckFilter(entry))
continue;
AddImageTiled(24, 94 + tableIndex * 32, canPrice ? 573 : 489, 2, 2624);
tableIndex += entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1;
}
AddAlphaRegion(18, 20, width - 17, 420);
AddImage(5, 5, 10460);
AddImage(width - 15, 5, 10460);
AddImage(5, 424, 10460);
AddImage(width - 15, 424, 10460);
AddHtmlLocalized(canPrice ? 266 : 224, 32, 200, 32, 1062220, LabelColor); // Bulk Order Book
AddHtmlLocalized(63, 64, 200, 32, 1062213, LabelColor); // Type
AddHtmlLocalized(147, 64, 200, 32, 1062214, LabelColor); // Item
AddHtmlLocalized(246, 64, 200, 32, 1062215, LabelColor); // Quality
AddHtmlLocalized(336, 64, 200, 32, 1062216, LabelColor); // Material
AddHtmlLocalized(429, 64, 200, 32, 1062217, LabelColor); // Amount
AddButton(35, 32, 4005, 4007, 1);
AddHtmlLocalized(70, 32, 200, 32, 1062476, LabelColor); // Set Filter
BOBFilter f = from.UseOwnFilter ? from.BOBFilter : book.Filter;
if (f.IsDefault)
AddHtmlLocalized(canPrice ? 470 : 386, 32, 120, 32, 1062475, 16927); // Using No Filter
else if (from.UseOwnFilter)
AddHtmlLocalized(canPrice ? 470 : 386, 32, 120, 32, 1062451, 16927); // Using Your Filter
else
AddHtmlLocalized(canPrice ? 470 : 386, 32, 120, 32, 1062230, 16927); // Using Book Filter
AddButton(375, 416, 4017, 4018, 0);
AddHtmlLocalized(410, 416, 120, 20, 1011441, LabelColor); // EXIT
if (canDrop)
AddHtmlLocalized(26, 64, 50, 32, 1062212, LabelColor); // Drop
if (canPrice)
{
AddHtmlLocalized(516, 64, 200, 32, 1062218, LabelColor); // Price
if (canBuy)
{
AddHtmlLocalized(576, 64, 200, 32, 1062219, LabelColor); // Buy
}
else
{
AddHtmlLocalized(576, 64, 200, 32, 1062227, LabelColor); // Set
AddButton(450, 416, 4005, 4007, 4);
AddHtml(485, 416, 120, 20, "<BASEFONT COLOR=#FFFFFF>Price all</FONT>");
}
}
tableIndex = 0;
if (page > 0)
{
AddButton(75, 416, 4014, 4016, 2);
AddHtmlLocalized(110, 416, 150, 20, 1011067, LabelColor); // Previous page
}
if (GetIndexForPage(page + 1) < list.Count)
{
AddButton(225, 416, 4005, 4007, 3);
AddHtmlLocalized(260, 416, 150, 20, 1011066, LabelColor); // Next page
}
for (int i = index; i < index + count && i >= 0 && i < list.Count; ++i)
{
IBOBEntry entry = list[i];
if (!CheckFilter(entry))
continue;
if (entry is BOBLargeEntry largeEntry)
{
int y = 96 + tableIndex * 32;
if (canDrop)
AddButton(35, y + 2, 5602, 5606, 5 + i * 2);
if (canDrop || canBuy && entry.Price > 0)
{
AddButton(579, y + 2, 2117, 2118, 6 + i * 2);
AddLabel(495, y, 1152, entry.Price.ToString());
}
AddHtmlLocalized(61, y, 50, 32, 1062225, LabelColor); // Large
for (int j = 0; j < largeEntry.Entries.Length; ++j)
{
BOBLargeSubEntry sub = largeEntry.Entries[j];
AddHtmlLocalized(103, y, 130, 32, sub.Number, LabelColor);
if (entry.RequireExceptional)
AddHtmlLocalized(235, y, 80, 20, 1060636, LabelColor); // exceptional
else
AddHtmlLocalized(235, y, 80, 20, 1011542, LabelColor); // normal
object name = GetMaterialName(entry.Material, entry.DeedType, sub.ItemType);
if (name is int intName)
AddHtmlLocalized(316, y, 100, 20, intName, LabelColor);
else
AddLabel(316, y, 1152, name.ToString());
AddLabel(421, y, 1152, $"{sub.AmountCur} / {entry.AmountMax}");
++tableIndex;
y += 32;
}
}
else
{
BOBSmallEntry smallEntry = (BOBSmallEntry)entry;
int y = 96 + tableIndex++ * 32;
if (canDrop)
AddButton(35, y + 2, 5602, 5606, 5 + i * 2);
if (canDrop || canBuy && smallEntry.Price > 0)
{
AddButton(579, y + 2, 2117, 2118, 6 + i * 2);
AddLabel(495, y, 1152, smallEntry.Price.ToString());
}
AddHtmlLocalized(61, y, 50, 32, 1062224, LabelColor); // Small
AddHtmlLocalized(103, y, 130, 32, smallEntry.Number, LabelColor);
if (smallEntry.RequireExceptional)
AddHtmlLocalized(235, y, 80, 20, 1060636, LabelColor); // exceptional
else
AddHtmlLocalized(235, y, 80, 20, 1011542, LabelColor); // normal
object name = GetMaterialName(smallEntry.Material, smallEntry.DeedType, smallEntry.ItemType);
if (name is int intName)
AddHtmlLocalized(316, y, 100, 20, intName, LabelColor);
else
AddLabel(316, y, 1152, name.ToString());
AddLabel(421, y, 1152, $"{smallEntry.AmountCur} / {smallEntry.AmountMax}");
}
}
}
public bool CheckFilter(IBOBEntry entry)
{
if (entry is BOBLargeEntry largeEntry)
return CheckFilter(entry.Material, entry.AmountMax, true, entry.RequireExceptional, entry.DeedType,
largeEntry.Entries.Length > 0 ? largeEntry.Entries[0].ItemType : null);
if (entry is BOBSmallEntry smallEntry)
return CheckFilter(entry.Material, entry.AmountMax, false, entry.RequireExceptional,
entry.DeedType, smallEntry.ItemType);
return false;
}
public bool CheckFilter(BulkMaterialType mat, int amountMax, bool isLarge, bool reqExc, BODType deedType,
Type itemType)
{
BOBFilter f = m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter;
if (f.IsDefault)
return true;
if (f.Quality == 1 && reqExc)
return false;
if (f.Quality == 2 && !reqExc)
return false;
if (f.Quantity == 1 && amountMax != 10)
return false;
if (f.Quantity == 2 && amountMax != 15)
return false;
if (f.Quantity == 3 && amountMax != 20)
return false;
if (f.Type == 1 && isLarge)
return false;
if (f.Type == 2 && !isLarge)
return false;
switch (f.Material)
{
default:
return true;
case 1: return deedType == BODType.Smith;
case 2: return deedType == BODType.Tailor;
case 3:
return mat == BulkMaterialType.None &&
BGTClassifier.Classify(deedType, itemType) == BulkGenericType.Iron;
case 4: return mat == BulkMaterialType.DullCopper;
case 5: return mat == BulkMaterialType.ShadowIron;
case 6: return mat == BulkMaterialType.Copper;
case 7: return mat == BulkMaterialType.Bronze;
case 8: return mat == BulkMaterialType.Gold;
case 9: return mat == BulkMaterialType.Agapite;
case 10: return mat == BulkMaterialType.Verite;
case 11: return mat == BulkMaterialType.Valorite;
case 12:
return mat == BulkMaterialType.None &&
BGTClassifier.Classify(deedType, itemType) == BulkGenericType.Cloth;
case 13:
return mat == BulkMaterialType.None &&
BGTClassifier.Classify(deedType, itemType) == BulkGenericType.Leather;
case 14: return mat == BulkMaterialType.Spined;
case 15: return mat == BulkMaterialType.Horned;
case 16: return mat == BulkMaterialType.Barbed;
}
}
public int GetIndexForPage(int page)
{
int index = 0;
while (page-- > 0)
index += GetCountForIndex(index);
return index;
}
public int GetCountForIndex(int index)
{
int slots = 0;
int count = 0;
List<IBOBEntry> list = m_List;
for (int i = index; i >= 0 && i < list.Count; ++i)
{
IBOBEntry entry = list[i];
if (CheckFilter(entry))
{
int add = entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1;
if (slots + add > 10)
break;
slots += add;
}
++count;
}
return count;
}
public int GetPageForIndex(int index, int sizeDropped)
{
if (index <= 0)
return 0;
int count = 0;
int page = 0;
int i;
List<IBOBEntry> list = m_List;
for (i = 0; i < index && i < list.Count; i++)
{
IBOBEntry entry = list[i];
if (!CheckFilter(entry))
continue;
int add = entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1;
count += add;
if (count > 10)
{
page++;
count = add;
}
}
/* now we are on the page of the bod preceding the dropped one.
* next step: checking whether we have to remain where we are.
* The counter i needs to be incremented as the bod to this very moment
* has not yet been removed from m_List */
i++;
/* if, for instance, a big bod of size 6 has been removed, smaller bods
* might fall back into this page. Depending on their sizes, the page needs
* to be adjusted accordingly. This is done now.
*/
if (count + sizeDropped > 10)
{
while (i < list.Count && count <= 10)
{
IBOBEntry entry = list[i];
if (CheckFilter(entry))
count += entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1;
i++;
}
if (count > 10)
page++;
}
return page;
}
public object GetMaterialName(BulkMaterialType mat, BODType type, Type itemType)
{
switch (type)
{
case BODType.Smith:
{
switch (mat)
{
case BulkMaterialType.None: return 1062226;
case BulkMaterialType.DullCopper: return 1018332;
case BulkMaterialType.ShadowIron: return 1018333;
case BulkMaterialType.Copper: return 1018334;
case BulkMaterialType.Bronze: return 1018335;
case BulkMaterialType.Gold: return 1018336;
case BulkMaterialType.Agapite: return 1018337;
case BulkMaterialType.Verite: return 1018338;
case BulkMaterialType.Valorite: return 1018339;
}
break;
}
case BODType.Tailor:
{
switch (mat)
{
case BulkMaterialType.None:
{
if (itemType.IsSubclassOf(typeof(BaseArmor)) || itemType.IsSubclassOf(typeof(BaseShoes)))
return 1062235;
return 1044286;
}
case BulkMaterialType.Spined: return 1062236;
case BulkMaterialType.Horned: return 1062237;
case BulkMaterialType.Barbed: return 1062238;
}
break;
}
}
return "Invalid";
}
public override void OnResponse(NetState sender, RelayInfo info)
{
int index = info.ButtonID;
switch (index)
{
case 0: // EXIT
{
break;
}
case 1: // Set Filter
{
m_From.SendGump(new BOBFilterGump(m_From, m_Book));
break;
}
case 2: // Previous page
{
if (m_Page > 0)
m_From.SendGump(new BOBGump(m_From, m_Book, m_Page - 1, m_List));
return;
}
case 3: // Next page
{
if (GetIndexForPage(m_Page + 1) < m_List.Count)
m_From.SendGump(new BOBGump(m_From, m_Book, m_Page + 1, m_List));
break;
}
case 4: // Price all
{
if (m_Book.IsChildOf(m_From.Backpack))
{
m_From.Prompt = new SetPricePrompt(m_Book, null, m_Page, m_List);
m_From.SendMessage("Type in a price for all deeds in the book:");
}
break;
}
default:
{
index -= 5;
int type = index % 2;
index /= 2;
if (index < 0 || index >= m_List.Count)
break;
IBOBEntry bobEntry = m_List[index];
if (!m_Book.Entries.Contains(bobEntry))
{
m_From.SendLocalizedMessage(1062382); // The deed selected is not available.
break;
}
if (type == 0) // Drop
{
if (m_Book.IsChildOf(m_From.Backpack))
{
Item item = bobEntry.Reconstruct();
Container pack = m_From.Backpack;
if (pack?.CheckHold(m_From, item, true, true, 0,
item.PileWeight + item.TotalWeight) != true)
{
m_From.SendLocalizedMessage(503204); // You do not have room in your backpack for this
m_From.SendGump(new BOBGump(m_From, m_Book, m_Page));
}
else
{
if (m_Book.IsChildOf(m_From.Backpack))
{
int sizeOfDroppedBod = bobEntry is BOBLargeEntry entry ? entry.Entries.Length : 1;
m_From.AddToBackpack(item);
m_From.SendLocalizedMessage(
1045152); // The bulk order deed has been placed in your backpack.
m_Book.Entries.Remove(bobEntry);
m_Book.InvalidateProperties();
if (m_Book.Entries.Count / 5 < m_Book.ItemCount)
{
m_Book.ItemCount--;
m_Book.InvalidateItems();
}
if (m_Book.Entries.Count > 0)
{
m_Page = GetPageForIndex(index, sizeOfDroppedBod);
m_From.SendGump(new BOBGump(m_From, m_Book, m_Page));
}
else
{
m_From.SendLocalizedMessage(1062381); // The book is empty.
}
}
}
}
}
else // Set Price | Buy
{
if (m_Book.IsChildOf(m_From.Backpack))
{
m_From.Prompt = new SetPricePrompt(m_Book, bobEntry, m_Page, m_List);
m_From.SendLocalizedMessage(1062383); // Type in a price for the deed:
}
else if (m_Book.RootParent is PlayerVendor pv)
{
VendorItem vi = pv.GetVendorItem(m_Book);
if (vi?.IsForSale != false)
return;
int sizeOfDroppedBod = bobEntry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1;
int price = bobEntry.Price;
if (price == 0)
{
m_From.SendLocalizedMessage(1062382); // The deed selected is not available.
}
else
{
if (m_Book.Entries.Count > 0)
{
m_Page = GetPageForIndex(index, sizeOfDroppedBod);
m_From.SendGump(new BODBuyGump(m_From, m_Book, bobEntry, m_Page, price));
}
else
{
m_From.SendLocalizedMessage(1062381); // The book is emptz
}
}
}
}
break;
}
}
}
private class SetPricePrompt : Prompt
{
private BulkOrderBook m_Book;
private List<IBOBEntry> m_List;
private IBOBEntry m_Entry;
private int m_Page;
public SetPricePrompt(BulkOrderBook book, IBOBEntry entry, int page, List<IBOBEntry> list)
{
m_Book = book;
m_Entry = entry;
m_Page = page;
m_List = list;
}
public override void OnResponse(Mobile from, string text)
{
if (m_Entry != null && !m_Book.Entries.Contains(m_Entry))
{
from.SendLocalizedMessage(1062382); // The deed selected is not available.
return;
}
int price = Utility.ToInt32(text);
if (price < 0 || price > 250000000)
{
from.SendLocalizedMessage(1062390); // The price you requested is outrageous!
}
else if (m_Entry == null)
{
for (int i = 0; i < m_List.Count; ++i)
{
IBOBEntry entry = m_List[i];
if (!m_Book.Entries.Contains(entry))
continue;
entry.Price = price;
}
from.SendMessage("Deed prices set.");
if (from is PlayerMobile mobile)
mobile.SendGump(new BOBGump(mobile, m_Book, m_Page, m_List));
}
else
{
m_Entry.Price = price;
from.SendLocalizedMessage(1062384); // Deed price set.
if (from is PlayerMobile mobile)
mobile.SendGump(new BOBGump(mobile, m_Book, m_Page, m_List));
}
}
}
}
}

View file

@ -0,0 +1,106 @@
namespace Server.Engines.BulkOrders
{
public class BOBLargeEntry: IBOBEntry
{
public BOBLargeEntry(LargeBOD bod)
{
RequireExceptional = bod.RequireExceptional;
if (bod is LargeTailorBOD)
DeedType = BODType.Tailor;
else if (bod is LargeSmithBOD)
DeedType = BODType.Smith;
Material = bod.Material;
AmountMax = bod.AmountMax;
Entries = new BOBLargeSubEntry[bod.Entries.Length];
for (int i = 0; i < Entries.Length; ++i)
Entries[i] = new BOBLargeSubEntry(bod.Entries[i]);
}
public BOBLargeEntry(GenericReader reader)
{
int version = reader.ReadEncodedInt();
switch (version)
{
case 0:
{
RequireExceptional = reader.ReadBool();
DeedType = (BODType)reader.ReadEncodedInt();
Material = (BulkMaterialType)reader.ReadEncodedInt();
AmountMax = reader.ReadEncodedInt();
Price = reader.ReadEncodedInt();
Entries = new BOBLargeSubEntry[reader.ReadEncodedInt()];
for (int i = 0; i < Entries.Length; ++i)
Entries[i] = new BOBLargeSubEntry(reader);
break;
}
}
}
public bool RequireExceptional{ get; }
public BODType DeedType{ get; }
public BulkMaterialType Material{ get; }
public int AmountMax{ get; }
public int Price{ get; set; }
public BOBLargeSubEntry[] Entries{ get; }
public Item Reconstruct()
{
LargeBOD bod = null;
if (DeedType == BODType.Smith)
bod = new LargeSmithBOD(AmountMax, RequireExceptional, Material, ReconstructEntries());
else if (DeedType == BODType.Tailor)
bod = new LargeTailorBOD(AmountMax, RequireExceptional, Material, ReconstructEntries());
for (int i = 0; bod?.Entries.Length >= i; ++i)
bod.Entries[i].Owner = bod;
return bod;
}
private LargeBulkEntry[] ReconstructEntries()
{
LargeBulkEntry[] entries = new LargeBulkEntry[Entries.Length];
for (int i = 0; i < Entries.Length; ++i)
{
entries[i] = new LargeBulkEntry(null,
new SmallBulkEntry(Entries[i].ItemType, Entries[i].Number, Entries[i].Graphic)) { Amount = Entries[i].AmountCur };
}
return entries;
}
public void Serialize(GenericWriter writer)
{
writer.WriteEncodedInt(0); // version
writer.Write(RequireExceptional);
writer.WriteEncodedInt((int)DeedType);
writer.WriteEncodedInt((int)Material);
writer.WriteEncodedInt(AmountMax);
writer.WriteEncodedInt(Price);
writer.WriteEncodedInt(Entries.Length);
for (int i = 0; i < Entries.Length; ++i)
Entries[i].Serialize(writer);
}
}
}

View file

@ -0,0 +1,56 @@
using System;
namespace Server.Engines.BulkOrders
{
public class BOBLargeSubEntry
{
public BOBLargeSubEntry(LargeBulkEntry lbe)
{
ItemType = lbe.Details.Type;
AmountCur = lbe.Amount;
Number = lbe.Details.Number;
Graphic = lbe.Details.Graphic;
}
public BOBLargeSubEntry(GenericReader reader)
{
int version = reader.ReadEncodedInt();
switch (version)
{
case 0:
{
string type = reader.ReadString();
if (type != null)
ItemType = ScriptCompiler.FindTypeByFullName(type);
AmountCur = reader.ReadEncodedInt();
Number = reader.ReadEncodedInt();
Graphic = reader.ReadEncodedInt();
break;
}
}
}
public Type ItemType{ get; }
public int AmountCur{ get; }
public int Number{ get; }
public int Graphic{ get; }
public void Serialize(GenericWriter writer)
{
writer.WriteEncodedInt(0); // version
writer.Write(ItemType == null ? null : ItemType.FullName);
writer.WriteEncodedInt(AmountCur);
writer.WriteEncodedInt(Number);
writer.WriteEncodedInt(Graphic);
}
}
}

View file

@ -0,0 +1,100 @@
using System;
namespace Server.Engines.BulkOrders
{
public class BOBSmallEntry : IBOBEntry
{
public BOBSmallEntry(SmallBOD bod)
{
ItemType = bod.Type;
RequireExceptional = bod.RequireExceptional;
if (bod is SmallTailorBOD)
DeedType = BODType.Tailor;
else if (bod is SmallSmithBOD)
DeedType = BODType.Smith;
Material = bod.Material;
AmountCur = bod.AmountCur;
AmountMax = bod.AmountMax;
Number = bod.Number;
Graphic = bod.Graphic;
}
public BOBSmallEntry(GenericReader reader)
{
int version = reader.ReadEncodedInt();
switch (version)
{
case 0:
{
string type = reader.ReadString();
if (type != null)
ItemType = ScriptCompiler.FindTypeByFullName(type);
RequireExceptional = reader.ReadBool();
DeedType = (BODType)reader.ReadEncodedInt();
Material = (BulkMaterialType)reader.ReadEncodedInt();
AmountCur = reader.ReadEncodedInt();
AmountMax = reader.ReadEncodedInt();
Number = reader.ReadEncodedInt();
Graphic = reader.ReadEncodedInt();
Price = reader.ReadEncodedInt();
break;
}
}
}
public Type ItemType{ get; }
public bool RequireExceptional{ get; }
public BODType DeedType{ get; }
public BulkMaterialType Material{ get; }
public int AmountCur{ get; }
public int AmountMax{ get; }
public int Number{ get; }
public int Graphic{ get; }
public int Price{ get; set; }
public Item Reconstruct()
{
SmallBOD bod = null;
if (DeedType == BODType.Smith)
bod = new SmallSmithBOD(AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material);
else if (DeedType == BODType.Tailor)
bod = new SmallTailorBOD(AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material);
return bod;
}
public void Serialize(GenericWriter writer)
{
writer.WriteEncodedInt(0); // version
writer.Write(ItemType == null ? null : ItemType.FullName);
writer.Write(RequireExceptional);
writer.WriteEncodedInt((int)DeedType);
writer.WriteEncodedInt((int)Material);
writer.WriteEncodedInt(AmountCur);
writer.WriteEncodedInt(AmountMax);
writer.WriteEncodedInt(Number);
writer.WriteEncodedInt(Graphic);
writer.WriteEncodedInt(Price);
}
}
}

View file

@ -0,0 +1,122 @@
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Network;
namespace Server.Engines.BulkOrders
{
public class BODBuyGump : Gump
{
private BulkOrderBook m_Book;
private PlayerMobile m_From;
private IBOBEntry m_Entry;
private int m_Page;
private int m_Price;
public BODBuyGump(PlayerMobile from, BulkOrderBook book, IBOBEntry entry, int page, int price) : base(100, 200)
{
m_From = from;
m_Book = book;
m_Entry = entry;
m_Price = price;
m_Page = page;
AddPage(0);
AddBackground(100, 10, 300, 150, 5054);
AddHtmlLocalized(125, 20, 250, 24, 1019070); // You have agreed to purchase:
AddHtmlLocalized(125, 45, 250, 24, 1045151); // a bulk order deed
AddHtmlLocalized(125, 70, 250, 24, 1019071); // for the amount of:
AddLabel(125, 95, 0, price.ToString());
AddButton(250, 130, 4005, 4007, 1);
AddHtmlLocalized(282, 130, 100, 24, 1011012); // CANCEL
AddButton(120, 130, 4005, 4007, 2);
AddHtmlLocalized(152, 130, 100, 24, 1011036); // OKAY
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID != 2)
{
m_From.SendLocalizedMessage(503207); // Cancelled purchase.
return;
}
if (!(m_Book.RootParent is PlayerVendor pv))
{
m_From.SendLocalizedMessage(1062382); // The deed selected is not available.
return;
}
if (!m_Book.Entries.Contains(m_Entry))
{
pv.SayTo(m_From, 1062382); // The deed selected is not available.
return;
}
int price = 0;
if (pv.GetVendorItem(m_Book)?.IsForSale == false)
price = m_Entry.Price;
if (price != m_Price)
{
pv.SayTo(m_From,
"The price has been been changed. If you like, you may offer to purchase the item again.");
return;
}
if (price == 0)
{
pv.SayTo(m_From, 1062382); // The deed selected is not available.
return;
}
Item item = m_Entry.Reconstruct();
pv.Say(m_From.Name);
Container pack = m_From.Backpack;
if (pack?.CheckHold(m_From, item, true, true, 0,
item.PileWeight + item.TotalWeight) != true)
{
pv.SayTo(m_From, 503204); // You do not have room in your backpack for this
m_From.SendGump(new BOBGump(m_From, m_Book, m_Page));
item.Delete();
}
else
{
if (pack.ConsumeTotal(typeof(Gold), price) || Banker.Withdraw(m_From, price))
{
m_Book.Entries.Remove(m_Entry);
m_Book.InvalidateProperties();
pv.HoldGold += price;
m_From.AddToBackpack(item);
m_From.SendLocalizedMessage(
1045152); // The bulk order deed has been placed in your backpack.
if (m_Book.Entries.Count / 5 < m_Book.ItemCount)
{
m_Book.ItemCount--;
m_Book.InvalidateItems();
}
if (m_Book.Entries.Count > 0)
m_From.SendGump(new BOBGump(m_From, m_Book, m_Page));
else
m_From.SendLocalizedMessage(1062381); // The book is empty.
}
else
{
pv.SayTo(m_From, 503205); // You cannot afford this item.
item.Delete();
}
}
}
}
}

View file

@ -0,0 +1,8 @@
namespace Server.Engines.BulkOrders
{
public enum BODType
{
Smith,
Tailor
}
}

View file

@ -0,0 +1,308 @@
using System.Collections.Generic;
using Server.Gumps;
using Server.Multis;
using Server.Prompts;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Items;
namespace Server.Engines.BulkOrders
{
public class BulkOrderBook : Item, ISecurable
{
private string m_BookName;
[CommandProperty( AccessLevel.GameMaster )]
public string BookName
{
get => m_BookName;
set{ m_BookName = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public SecureLevel Level { get; set; }
public List<IBOBEntry> Entries { get; private set; }
public BOBFilter Filter { get; private set; }
public int ItemCount { get; set; }
[Constructible]
public BulkOrderBook() : base( 0x2259 )
{
Weight = 1.0;
LootType = LootType.Blessed;
Entries = new List<IBOBEntry>();
Filter = new BOBFilter();
Level = SecureLevel.CoOwners;
}
public override void OnDoubleClick( Mobile from )
{
if ( !from.InRange( GetWorldLocation(), 2 ) )
from.LocalOverheadMessage( Network.MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
else if ( Entries.Count == 0 )
from.SendLocalizedMessage( 1062381 ); // The book is empty.
else if ( from is PlayerMobile mobile )
mobile.SendGump( new BOBGump( mobile, this ) );
}
public override void OnDoubleClickSecureTrade( Mobile from )
{
if ( !from.InRange( GetWorldLocation(), 2 ) )
{
from.SendLocalizedMessage( 500446 ); // That is too far away.
}
else if ( Entries.Count == 0 )
{
from.SendLocalizedMessage( 1062381 ); // The book is empty.
}
else
{
from.SendGump( new BOBGump( (PlayerMobile)from, this ) );
SecureTrade trade = GetSecureTradeCont()?.Trade;
if (trade?.From.Mobile == from )
trade.To.Mobile.SendGump( new BOBGump( (PlayerMobile)trade.To.Mobile, this ) );
else if (trade?.To.Mobile == from )
trade.From.Mobile.SendGump( new BOBGump( (PlayerMobile)trade.From.Mobile, this ) );
}
}
public override bool OnDragDrop( Mobile from, Item dropped )
{
if ( dropped is BaseBOD )
{
if ( !IsChildOf( from.Backpack ) )
{
from.SendLocalizedMessage( 1062385 ); // You must have the book in your backpack to add deeds to it.
return false;
}
if ( !from.Backpack.CheckHold( from, dropped, true, true ) )
return false;
if ( Entries.Count < 500 )
{
if ( dropped is LargeBOD bod )
Entries.Add( new BOBLargeEntry( bod ) );
else
Entries.Add( new BOBSmallEntry( (SmallBOD)dropped ) );
InvalidateProperties();
if ( Entries.Count / 5 > ItemCount )
{
ItemCount++;
InvalidateItems();
}
from.SendSound(0x42, GetWorldLocation());
from.SendLocalizedMessage( 1062386 ); // Deed added to book.
if ( from is PlayerMobile pm )
pm.SendGump( new BOBGump( pm, this ) );
dropped.Delete();
return true;
}
from.SendLocalizedMessage( 1062387 ); // The book is full of deeds.
return false;
}
from.SendLocalizedMessage( 1062388 ); // That is not a bulk order deed.
return false;
}
public override int GetTotal( TotalType type )
{
int total = base.GetTotal( type );
if ( type == TotalType.Items )
total = ItemCount;
return total;
}
public void InvalidateItems()
{
if ( RootParent is Mobile m )
{
m.UpdateTotals();
InvalidateContainers( Parent );
}
}
public void InvalidateContainers(IEntity parent)
{
if ( parent is Container c )
{
c.InvalidateProperties();
InvalidateContainers( c.Parent );
}
}
public BulkOrderBook( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( 2 ); // version
writer.Write( ItemCount );
writer.Write( (int) Level );
writer.Write( m_BookName );
Filter.Serialize( writer );
writer.WriteEncodedInt( Entries.Count );
for ( int i = 0; i < Entries.Count; ++i )
{
object obj = Entries[i];
if ( obj is BOBLargeEntry entry )
{
writer.WriteEncodedInt( 0 );
entry.Serialize( writer );
}
else
{
writer.WriteEncodedInt( 1 );
((BOBSmallEntry)obj).Serialize( writer );
}
}
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
switch ( version )
{
case 2:
{
ItemCount = reader.ReadInt();
goto case 1;
}
case 1:
{
Level = (SecureLevel)reader.ReadInt();
goto case 0;
}
case 0:
{
m_BookName = reader.ReadString();
Filter = new BOBFilter( reader );
int count = reader.ReadEncodedInt();
Entries = new List<IBOBEntry>( count );
for ( int i = 0; i < count; ++i )
{
int v = reader.ReadEncodedInt();
switch ( v )
{
case 0: Entries.Add( new BOBLargeEntry( reader ) ); break;
case 1: Entries.Add( new BOBSmallEntry( reader ) ); break;
}
}
break;
}
}
}
public override void GetProperties( ObjectPropertyList list )
{
base.GetProperties( list );
list.Add( 1062344, Entries.Count.ToString() ); // Deeds in book: ~1_val~
if ( !string.IsNullOrEmpty(m_BookName) )
list.Add( 1062481, m_BookName ); // Book Name: ~1_val~
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
LabelTo(from, 1062344, Entries.Count.ToString()); // Deeds in book: ~1_val~
if (!string.IsNullOrEmpty(m_BookName))
LabelTo(from, 1062481, m_BookName);
}
public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
{
base.GetContextMenuEntries( from, list );
if ( from.CheckAlive() && IsChildOf( from.Backpack ) )
list.Add( new NameBookEntry( from, this ) );
SetSecureLevelEntry.AddTo( from, this, list );
}
private class NameBookEntry : ContextMenuEntry
{
private Mobile m_From;
private BulkOrderBook m_Book;
public NameBookEntry( Mobile from, BulkOrderBook book ) : base( 6216 )
{
m_From = from;
m_Book = book;
}
public override void OnClick()
{
if ( m_From.CheckAlive() && m_Book.IsChildOf( m_From.Backpack ) )
{
m_From.Prompt = new NameBookPrompt( m_Book );
m_From.SendLocalizedMessage( 1062479 ); // Type in the new name of the book:
}
}
}
private class NameBookPrompt : Prompt
{
private BulkOrderBook m_Book;
public NameBookPrompt( BulkOrderBook book )
{
m_Book = book;
}
public override void OnResponse( Mobile from, string text )
{
if ( text.Length > 40 )
text = text.Substring( 0, 40 );
if ( from.CheckAlive() && m_Book.IsChildOf( from.Backpack ) )
{
m_Book.BookName = Utility.FixHtml( text.Trim() );
from.SendLocalizedMessage( 1062480 ); // The bulk order book's name has been changed.
}
}
public override void OnCancel( Mobile from )
{
}
}
}
}

View file

@ -0,0 +1,12 @@
namespace Server.Engines.BulkOrders
{
public interface IBOBEntry
{
bool RequireExceptional{ get; }
BODType DeedType{ get; }
BulkMaterialType Material{ get; }
int AmountMax{ get; }
int Price{ get; set; }
Item Reconstruct();
}
}

View file

@ -0,0 +1,40 @@
using System;
using Server.Items;
namespace Server.Engines.BulkOrders
{
public enum BulkMaterialType
{
None,
DullCopper,
ShadowIron,
Copper,
Bronze,
Gold,
Agapite,
Verite,
Valorite,
Spined,
Horned,
Barbed
}
public enum BulkGenericType
{
Iron,
Cloth,
Leather
}
public class BGTClassifier
{
public static BulkGenericType Classify(BODType deedType, Type itemType)
{
if (deedType != BODType.Tailor)
return BulkGenericType.Iron;
return itemType == null || itemType.IsSubclassOf(typeof(BaseArmor)) || itemType.IsSubclassOf(typeof(BaseShoes))
? BulkGenericType.Leather : BulkGenericType.Cloth;
}
}
}

View file

@ -0,0 +1,175 @@
using Server.Mobiles;
namespace Server.Engines.BulkOrders
{
public abstract class LargeBOD : BaseBOD
{
private LargeBulkEntry[] m_Entries;
public LargeBulkEntry[] Entries
{
get => m_Entries;
set{ m_Entries = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public override bool Complete
{
get
{
for ( int i = 0; i < m_Entries.Length; ++i )
if ( m_Entries[i].Amount < AmountMax )
return false;
return true;
}
}
public override int LabelNumber => 1045151; // a bulk order deed
public LargeBOD(int hue, int amountMax, bool requireExeptional, BulkMaterialType material, LargeBulkEntry[] entries) :
base(hue, amountMax, requireExeptional, material)
{
m_Entries = entries;
}
public LargeBOD()
{
}
public override void GetProperties( ObjectPropertyList list )
{
base.GetProperties( list );
list.Add( 1060655 ); // large bulk order
if ( RequireExceptional )
list.Add( 1045141 ); // All items must be exceptional.
if ( Material != BulkMaterialType.None )
list.Add( LargeBODGump.GetMaterialNumberFor( Material ) ); // All items must be made with x material.
list.Add( 1060656, AmountMax.ToString() ); // amount to make: ~1_val~
for ( int i = 0; i < m_Entries.Length; ++i )
list.Add( 1060658 + i, "#{0}\t{1}", m_Entries[i].Details.Number, m_Entries[i].Amount ); // ~1_val~: ~2_val~
}
public override void OnDoubleClickNotAccessible( Mobile from )
{
OnDoubleClick( from );
}
public override void OnDoubleClickSecureTrade( Mobile from )
{
OnDoubleClick( from );
}
public override void OnDoubleClick( Mobile from )
{
if ( IsChildOf( from.Backpack ) || InSecureTrade || RootParent is PlayerVendor )
from.SendGump( new LargeBODGump( from, this ) );
else
from.SendLocalizedMessage( 1045156 ); // You must have the deed in your backpack to use it.
}
public override void EndCombine(Mobile from, Item item)
{
if (!(item is SmallBOD small))
{
from.SendLocalizedMessage(1045159); // That is not a bulk order.
return;
}
LargeBulkEntry entry = null;
for (int i = 0; i < m_Entries.Length; ++i)
{
if (m_Entries[i].Details.Type == small.Type)
{
entry = m_Entries[i];
break;
}
}
if (entry == null)
{
from.SendLocalizedMessage(1045160); // That is not a bulk order for this large request.
}
else if (RequireExceptional && !small.RequireExceptional)
{
from.SendLocalizedMessage(1045161); // Both orders must be of exceptional quality.
}
else if (Material >= BulkMaterialType.DullCopper && Material <= BulkMaterialType.Valorite &&
small.Material != Material)
{
from.SendLocalizedMessage(1045162); // Both orders must use the same ore type.
}
else if (Material >= BulkMaterialType.Spined && Material <= BulkMaterialType.Barbed &&
small.Material != Material)
{
from.SendLocalizedMessage(1049351); // Both orders must use the same leather type.
}
else if (AmountMax != small.AmountMax)
{
from.SendLocalizedMessage(1045163); // The two orders have different requested amounts and cannot be combined.
}
else if (small.AmountCur < small.AmountMax)
{
from.SendLocalizedMessage(1045164); // The order to combine with is not completed.
}
else if (entry.Amount >= AmountMax)
{
from.SendLocalizedMessage(
1045166); // The maximum amount of requested items have already been combined to this deed.
}
else
{
entry.Amount += small.AmountCur;
small.Delete();
from.SendLocalizedMessage(1045165); // The orders have been combined.
from.SendGump(new LargeBODGump(from, this));
if (!Complete)
BeginCombine(from);
}
}
public LargeBOD(Serial serial) : base(serial)
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( 0 ); // version
writer.Write( m_Entries.Length );
for ( int i = 0; i < m_Entries.Length; ++i )
m_Entries[i].Serialize( writer );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
switch ( version )
{
case 0:
{
m_Entries = new LargeBulkEntry[reader.ReadInt()];
for ( int i = 0; i < m_Entries.Length; ++i )
m_Entries[i] = new LargeBulkEntry( this, reader );
break;
}
}
}
}
}

View file

@ -0,0 +1,110 @@
using Server.Gumps;
using Server.Network;
namespace Server.Engines.BulkOrders
{
public class LargeBODAcceptGump : Gump
{
private LargeBOD m_Deed;
private Mobile m_From;
public LargeBODAcceptGump(Mobile from, LargeBOD deed) : base(50, 50)
{
m_From = from;
m_Deed = deed;
m_From.CloseGump<LargeBODAcceptGump>();
m_From.CloseGump<SmallBODAcceptGump>();
LargeBulkEntry[] entries = deed.Entries;
AddPage(0);
AddBackground(25, 10, 430, 240 + entries.Length * 24, 5054);
AddImageTiled(33, 20, 413, 221 + entries.Length * 24, 2624);
AddAlphaRegion(33, 20, 413, 221 + entries.Length * 24);
AddImage(20, 5, 10460);
AddImage(430, 5, 10460);
AddImage(20, 225 + entries.Length * 24, 10460);
AddImage(430, 225 + entries.Length * 24, 10460);
AddHtmlLocalized(180, 25, 120, 20, 1045134, 0x7FFF); // A large bulk order
AddHtmlLocalized(40, 48, 350, 20, 1045135, 0x7FFF); // Ah! Thanks for the goods! Would you help me out?
AddHtmlLocalized(40, 72, 210, 20, 1045138, 0x7FFF); // Amount to make:
AddLabel(250, 72, 1152, deed.AmountMax.ToString());
AddHtmlLocalized(40, 96, 120, 20, 1045137, 0x7FFF); // Items requested:
int y = 120;
for (int i = 0; i < entries.Length; ++i, y += 24)
AddHtmlLocalized(40, y, 210, 20, entries[i].Details.Number, 0x7FFF);
if (deed.RequireExceptional || deed.Material != BulkMaterialType.None)
{
AddHtmlLocalized(40, y, 210, 20, 1045140, 0x7FFF); // Special requirements to meet:
y += 24;
if (deed.RequireExceptional)
{
AddHtmlLocalized(40, y, 350, 20, 1045141, 0x7FFF); // All items must be exceptional.
y += 24;
}
if (deed.Material != BulkMaterialType.None)
{
AddHtmlLocalized(40, y, 350, 20, GetMaterialNumberFor(deed.Material), 0x7FFF); // All items must be made with x material.
y += 24;
}
}
AddHtmlLocalized(40, 192 + entries.Length * 24, 350, 20, 1045139, 0x7FFF); // Do you want to accept this order?
AddButton(100, 216 + entries.Length * 24, 4005, 4007, 1);
AddHtmlLocalized(135, 216 + entries.Length * 24, 120, 20, 1006044, 0x7FFF); // Ok
AddButton(275, 216 + entries.Length * 24, 4005, 4007, 0);
AddHtmlLocalized(310, 216 + entries.Length * 24, 120, 20, 1011012, 0x7FFF); // CANCEL
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID == 1) // Ok
{
if (m_From.PlaceInBackpack(m_Deed))
{
m_From.SendLocalizedMessage(1045152); // The bulk order deed has been placed in your backpack.
}
else
{
m_From.SendLocalizedMessage(1045150); // There is not enough room in your backpack for the deed.
m_Deed.Delete();
}
}
else
{
m_Deed.Delete();
}
}
public override void OnServerClose(NetState owner)
{
if (m_Deed?.Deleted == false)
m_Deed.Delete();
}
public static int GetMaterialNumberFor(BulkMaterialType material)
{
if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite)
return 1045142 + (material - BulkMaterialType.DullCopper);
if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed)
return 1049348 + (material - BulkMaterialType.Spined);
return 0;
}
}
}

View file

@ -0,0 +1,98 @@
using Server.Gumps;
using Server.Network;
namespace Server.Engines.BulkOrders
{
public class LargeBODGump : Gump
{
private LargeBOD m_Deed;
private Mobile m_From;
public LargeBODGump(Mobile from, LargeBOD deed) : base(25, 25)
{
m_From = from;
m_Deed = deed;
m_From.CloseGump<LargeBODGump>();
m_From.CloseGump<SmallBODGump>();
LargeBulkEntry[] entries = deed.Entries;
AddPage(0);
AddBackground(50, 10, 455, 236 + entries.Length * 24, 5054);
AddImageTiled(58, 20, 438, 217 + entries.Length * 24, 2624);
AddAlphaRegion(58, 20, 438, 217 + entries.Length * 24);
AddImage(45, 5, 10460);
AddImage(480, 5, 10460);
AddImage(45, 221 + entries.Length * 24, 10460);
AddImage(480, 221 + entries.Length * 24, 10460);
AddHtmlLocalized(225, 25, 120, 20, 1045134, 0x7FFF); // A large bulk order
AddHtmlLocalized(75, 48, 250, 20, 1045138, 0x7FFF); // Amount to make:
AddLabel(275, 48, 1152, deed.AmountMax.ToString());
AddHtmlLocalized(75, 72, 120, 20, 1045137, 0x7FFF); // Items requested:
AddHtmlLocalized(275, 76, 200, 20, 1045153, 0x7FFF); // Amount finished:
int y = 96;
for (int i = 0; i < entries.Length; ++i)
{
LargeBulkEntry entry = entries[i];
SmallBulkEntry details = entry.Details;
AddHtmlLocalized(75, y, 210, 20, details.Number, 0x7FFF);
AddLabel(275, y, 0x480, entry.Amount.ToString());
y += 24;
}
if (deed.RequireExceptional || deed.Material != BulkMaterialType.None)
{
AddHtmlLocalized(75, y, 200, 20, 1045140, 0x7FFF); // Special requirements to meet:
y += 24;
}
if (deed.RequireExceptional)
{
AddHtmlLocalized(75, y, 300, 20, 1045141, 0x7FFF); // All items must be exceptional.
y += 24;
}
if (deed.Material != BulkMaterialType.None)
AddHtmlLocalized(75, y, 300, 20, GetMaterialNumberFor(deed.Material), 0x7FFF); // All items must be made with x material.
AddButton(125, 168 + entries.Length * 24, 4005, 4007, 2);
AddHtmlLocalized(160, 168 + entries.Length * 24, 300, 20, 1045155, 0x7FFF); // Combine this deed with another deed.
AddButton(125, 192 + entries.Length * 24, 4005, 4007, 1);
AddHtmlLocalized(160, 192 + entries.Length * 24, 120, 20, 1011441, 0x7FFF); // EXIT
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_Deed.Deleted || !m_Deed.IsChildOf(m_From.Backpack))
return;
if (info.ButtonID == 2) // Combine
{
m_From.SendGump(new LargeBODGump(m_From, m_Deed));
m_Deed.BeginCombine(m_From);
}
}
public static int GetMaterialNumberFor(BulkMaterialType material)
{
if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite)
return 1045142 + (material - BulkMaterialType.DullCopper);
if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed)
return 1049348 + (material - BulkMaterialType.Spined);
return 0;
}
}
}

View file

@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
namespace Server.Engines.BulkOrders
{
public class LargeBulkEntry
{
private int m_Amount;
public LargeBOD Owner { get; set; }
public int Amount
{
get => m_Amount;
set{ m_Amount = value; Owner?.InvalidateProperties(); }
}
public SmallBulkEntry Details { get; }
public static SmallBulkEntry[] LargeRing => GetEntries( "Blacksmith", "largering" );
public static SmallBulkEntry[] LargePlate => GetEntries( "Blacksmith", "largeplate" );
public static SmallBulkEntry[] LargeChain => GetEntries( "Blacksmith", "largechain" );
public static SmallBulkEntry[] LargeAxes => GetEntries( "Blacksmith", "largeaxes" );
public static SmallBulkEntry[] LargeFencing => GetEntries( "Blacksmith", "largefencing" );
public static SmallBulkEntry[] LargeMaces => GetEntries( "Blacksmith", "largemaces" );
public static SmallBulkEntry[] LargePolearms => GetEntries( "Blacksmith", "largepolearms" );
public static SmallBulkEntry[] LargeSwords => GetEntries( "Blacksmith", "largeswords" );
public static SmallBulkEntry[] BoneSet => GetEntries( "Tailoring", "boneset" );
public static SmallBulkEntry[] Farmer => GetEntries( "Tailoring", "farmer" );
public static SmallBulkEntry[] FemaleLeatherSet => GetEntries( "Tailoring", "femaleleatherset" );
public static SmallBulkEntry[] FisherGirl => GetEntries( "Tailoring", "fishergirl" );
public static SmallBulkEntry[] Gypsy => GetEntries( "Tailoring", "gypsy" );
public static SmallBulkEntry[] HatSet => GetEntries( "Tailoring", "hatset" );
public static SmallBulkEntry[] Jester => GetEntries( "Tailoring", "jester" );
public static SmallBulkEntry[] Lady => GetEntries( "Tailoring", "lady" );
public static SmallBulkEntry[] MaleLeatherSet => GetEntries( "Tailoring", "maleleatherset" );
public static SmallBulkEntry[] Pirate => GetEntries( "Tailoring", "pirate" );
public static SmallBulkEntry[] ShoeSet => GetEntries( "Tailoring", "shoeset" );
public static SmallBulkEntry[] StuddedSet => GetEntries( "Tailoring", "studdedset" );
public static SmallBulkEntry[] TownCrier => GetEntries( "Tailoring", "towncrier" );
public static SmallBulkEntry[] Wizard => GetEntries( "Tailoring", "wizard" );
private static Dictionary<string,Dictionary<string,SmallBulkEntry[]>> m_Cache;
public static SmallBulkEntry[] GetEntries( string type, string name )
{
if (m_Cache == null)
m_Cache = new Dictionary<string, Dictionary<string, SmallBulkEntry[]>>();
if (!m_Cache.TryGetValue( type, out Dictionary<string, SmallBulkEntry[]> table ))
m_Cache[type] = table = new Dictionary<string, SmallBulkEntry[]>();
if (!table.TryGetValue( name, out SmallBulkEntry[] entries ))
table[name] = entries = SmallBulkEntry.LoadEntries(type, name);
return entries;
}
public static LargeBulkEntry[] ConvertEntries( LargeBOD owner, SmallBulkEntry[] small )
{
LargeBulkEntry[] large = new LargeBulkEntry[small.Length];
for ( int i = 0; i < small.Length; ++i )
large[i] = new LargeBulkEntry( owner, small[i] );
return large;
}
public LargeBulkEntry( LargeBOD owner, SmallBulkEntry details )
{
Owner = owner;
Details = details;
}
public LargeBulkEntry( LargeBOD owner, GenericReader reader )
{
Owner = owner;
m_Amount = reader.ReadInt();
Type realType = null;
string type = reader.ReadString();
if ( type != null )
realType = ScriptCompiler.FindTypeByFullName( type );
Details = new SmallBulkEntry( realType, reader.ReadInt(), reader.ReadInt() );
}
public void Serialize( GenericWriter writer )
{
writer.Write( m_Amount );
writer.Write( Details.Type == null ? null : Details.Type.FullName );
writer.Write( Details.Number );
writer.Write( Details.Graphic );
}
}
}

View file

@ -0,0 +1,102 @@
namespace Server.Engines.BulkOrders
{
public class LargeSmithBOD : LargeBOD
{
public static double[] m_BlacksmithMaterialChances =
{
0.501953125, // None
0.250000000, // Dull Copper
0.125000000, // Shadow Iron
0.062500000, // Copper
0.031250000, // Bronze
0.015625000, // Gold
0.007812500, // Agapite
0.003906250, // Verite
0.001953125 // Valorite
};
[Constructible]
public LargeSmithBOD()
{
LargeBulkEntry[] entries;
bool useMaterials = true;
int rand = Utility.Random(8);
switch (rand)
{
default:
case 0:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeRing);
break;
case 1:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargePlate);
break;
case 2:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeChain);
break;
case 3:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeAxes);
break;
case 4:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeFencing);
break;
case 5:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeMaces);
break;
case 6:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargePolearms);
break;
case 7:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeSwords);
break;
}
if (rand > 2 && rand < 8)
useMaterials = false;
int hue = 0x44E;
int amountMax = Utility.RandomList(10, 15, 20, 20);
bool reqExceptional = 0.825 > Utility.RandomDouble();
BulkMaterialType material = useMaterials ? GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances)
: BulkMaterialType.None;
Hue = hue;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = material;
}
public LargeSmithBOD(int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries)
: base(0x44E, amountMax, reqExceptional, mat, entries)
{
}
public LargeSmithBOD(Serial serial) : base(serial)
{
}
public override int ComputeFame() => SmithRewardCalculator.Instance.ComputeFame(this);
public override int ComputeGold() => SmithRewardCalculator.Instance.ComputeGold(this);
public override RewardGroup GetRewardGroup() =>
SmithRewardCalculator.Instance.LookupRewards(SmithRewardCalculator.Instance.ComputePoints(this));
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,121 @@
namespace Server.Engines.BulkOrders
{
public class LargeTailorBOD : LargeBOD
{
public static double[] m_TailoringMaterialChances =
{
0.857421875, // None
0.125000000, // Spined
0.015625000, // Horned
0.001953125 // Barbed
};
[Constructible]
public LargeTailorBOD()
{
LargeBulkEntry[] entries;
bool useMaterials = false;
switch (Utility.Random(14))
{
default:
case 0:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Farmer);
break;
case 1:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.FemaleLeatherSet);
useMaterials = true;
break;
case 2:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.FisherGirl);
break;
case 3:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Gypsy);
break;
case 4:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.HatSet);
break;
case 5:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Jester);
break;
case 6:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Lady);
break;
case 7:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.MaleLeatherSet);
useMaterials = true;
break;
case 8:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Pirate);
break;
case 9:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.ShoeSet);
useMaterials = Core.ML;
break;
case 10:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.StuddedSet);
useMaterials = true;
break;
case 11:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.TownCrier);
break;
case 12:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Wizard);
break;
case 13:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.BoneSet);
useMaterials = true;
break;
}
int hue = 0x483;
int amountMax = Utility.RandomList(10, 15, 20, 20);
bool reqExceptional = 0.825 > Utility.RandomDouble();
BulkMaterialType material = useMaterials ? GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances)
: BulkMaterialType.None;
Hue = hue;
AmountMax = amountMax;
Entries = entries;
RequireExceptional = reqExceptional;
Material = material;
}
public LargeTailorBOD(int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries)
: base(0x483, amountMax, reqExceptional, mat, entries)
{
}
public LargeTailorBOD(Serial serial) : base(serial)
{
}
public override int ComputeFame()
{
return TailorRewardCalculator.Instance.ComputeFame(this);
}
public override int ComputeGold()
{
return TailorRewardCalculator.Instance.ComputeGold(this);
}
public override RewardGroup GetRewardGroup() =>
TailorRewardCalculator.Instance.LookupRewards(TailorRewardCalculator.Instance.ComputePoints(this));
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,745 @@
using System;
using Server.Items;
namespace Server.Engines.BulkOrders
{
public delegate Item ConstructCallback(int type);
public sealed class RewardType
{
public RewardType(int points, params Type[] types)
{
Points = points;
Types = types;
}
public int Points{ get; }
public Type[] Types{ get; }
public bool Contains(Type type)
{
for (int i = 0; i < Types.Length; ++i)
if (Types[i] == type)
return true;
return false;
}
}
public sealed class RewardItem
{
public RewardItem(int weight, ConstructCallback constructor, int type = 0)
{
Weight = weight;
Constructor = constructor;
Type = type;
}
public int Weight{ get; }
public ConstructCallback Constructor{ get; }
public int Type{ get; }
public Item Construct()
{
try
{
return Constructor(Type);
}
catch
{
return null;
}
}
}
public sealed class RewardGroup
{
public RewardGroup(int points, params RewardItem[] items)
{
Points = points;
Items = items;
}
public int Points{ get; }
public RewardItem[] Items{ get; }
public RewardItem AcquireItem()
{
if (Items.Length == 0)
return null;
if (Items.Length == 1)
return Items[0];
int totalWeight = 0;
for (int i = 0; i < Items.Length; ++i)
totalWeight += Items[i].Weight;
int randomWeight = Utility.Random(totalWeight);
for (int i = 0; i < Items.Length; ++i)
{
RewardItem item = Items[i];
if (randomWeight < item.Weight)
return item;
randomWeight -= item.Weight;
}
return null;
}
}
public abstract class RewardCalculator
{
public RewardGroup[] Groups{ get; set; }
public abstract int ComputePoints(int quantity, bool exceptional, BulkMaterialType material, int itemCount,
Type type);
public abstract int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type);
public virtual int ComputeFame(SmallBOD bod)
{
int points = ComputePoints(bod) / 50;
return points * points;
}
public virtual int ComputeFame(LargeBOD bod)
{
int points = ComputePoints(bod) / 50;
return points * points;
}
public virtual int ComputePoints(SmallBOD bod)
{
return ComputePoints(bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type);
}
public virtual int ComputePoints(LargeBOD bod)
{
return ComputePoints(bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length,
bod.Entries[0].Details.Type);
}
public virtual int ComputeGold(SmallBOD bod)
{
return ComputeGold(bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type);
}
public virtual int ComputeGold(LargeBOD bod)
{
return ComputeGold(bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length,
bod.Entries[0].Details.Type);
}
public virtual RewardGroup LookupRewards(int points)
{
for (int i = Groups.Length - 1; i >= 1; --i)
{
RewardGroup group = Groups[i];
if (points >= group.Points)
return group;
}
return Groups[0];
}
public virtual int LookupTypePoints(RewardType[] types, Type type)
{
for (int i = 0; i < types.Length; ++i)
if (types[i].Contains(type))
return types[i].Points;
return 0;
}
}
public sealed class SmithRewardCalculator : RewardCalculator
{
private static readonly ConstructCallback SturdyShovel = CreateSturdyShovel;
private static readonly ConstructCallback SturdyPickaxe = CreateSturdyPickaxe;
private static readonly ConstructCallback MiningGloves = CreateMiningGloves;
private static readonly ConstructCallback GargoylesPickaxe = CreateGargoylesPickaxe;
private static readonly ConstructCallback ProspectorsTool = CreateProspectorsTool;
private static readonly ConstructCallback PowderOfTemperament = CreatePowderOfTemperament;
private static readonly ConstructCallback RunicHammer = CreateRunicHammer;
private static readonly ConstructCallback PowerScroll = CreatePowerScroll;
private static readonly ConstructCallback ColoredAnvil = CreateColoredAnvil;
private static readonly ConstructCallback AncientHammer = CreateAncientHammer;
public static readonly SmithRewardCalculator Instance = new SmithRewardCalculator();
private static int[][][] m_GoldTable =
{
new[] // 1-part (regular)
{
new[] { 150, 250, 250, 400, 400, 750, 750, 1200, 1200 },
new[] { 225, 375, 375, 600, 600, 1125, 1125, 1800, 1800 },
new[] { 300, 500, 750, 800, 1050, 1500, 2250, 2400, 4000 }
},
new[] // 1-part (exceptional)
{
new[] { 250, 400, 400, 750, 750, 1500, 1500, 3000, 3000 },
new[] { 375, 600, 600, 1125, 1125, 2250, 2250, 4500, 4500 },
new[] { 500, 800, 1200, 1500, 2500, 3000, 6000, 6000, 12000 }
},
new[] // Ringmail (regular)
{
new[] { 3000, 5000, 5000, 7500, 7500, 10000, 10000, 15000, 15000 },
new[] { 4500, 7500, 7500, 11250, 11500, 15000, 15000, 22500, 22500 },
new[] { 6000, 10000, 15000, 15000, 20000, 20000, 30000, 30000, 50000 }
},
new[] // Ringmail (exceptional)
{
new[] { 5000, 10000, 10000, 15000, 15000, 25000, 25000, 50000, 50000 },
new[] { 7500, 15000, 15000, 22500, 22500, 37500, 37500, 75000, 75000 },
new[] { 10000, 20000, 30000, 30000, 50000, 50000, 100000, 100000, 200000 }
},
new[] // Chainmail (regular)
{
new[] { 4000, 7500, 7500, 10000, 10000, 15000, 15000, 25000, 25000 },
new[] { 6000, 11250, 11250, 15000, 15000, 22500, 22500, 37500, 37500 },
new[] { 8000, 15000, 20000, 20000, 30000, 30000, 50000, 50000, 100000 }
},
new[] // Chainmail (exceptional)
{
new[] { 7500, 15000, 15000, 25000, 25000, 50000, 50000, 100000, 100000 },
new[] { 11250, 22500, 22500, 37500, 37500, 75000, 75000, 150000, 150000 },
new[] { 15000, 30000, 50000, 50000, 100000, 100000, 200000, 200000, 200000 }
},
new[] // Platemail (regular)
{
new[] { 5000, 10000, 10000, 15000, 15000, 25000, 25000, 50000, 50000 },
new[] { 7500, 15000, 15000, 22500, 22500, 37500, 37500, 75000, 75000 },
new[] { 10000, 20000, 30000, 30000, 50000, 50000, 100000, 100000, 200000 }
},
new[] // Platemail (exceptional)
{
new[] { 10000, 25000, 25000, 50000, 50000, 100000, 100000, 100000, 100000 },
new[] { 15000, 37500, 37500, 75000, 75000, 150000, 150000, 150000, 150000 },
new[] { 20000, 50000, 100000, 100000, 200000, 200000, 200000, 200000, 200000 }
},
new[] // 2-part weapons (regular)
{
new[] { 3000, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 4500, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 6000, 0, 0, 0, 0, 0, 0, 0, 0 }
},
new[] // 2-part weapons (exceptional)
{
new[] { 5000, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 7500, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 10000, 0, 0, 0, 0, 0, 0, 0, 0 }
},
new[] // 5-part weapons (regular)
{
new[] { 4000, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 6000, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 8000, 0, 0, 0, 0, 0, 0, 0, 0 }
},
new[] // 5-part weapons (exceptional)
{
new[] { 7500, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 11250, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 15000, 0, 0, 0, 0, 0, 0, 0, 0 }
},
new[] // 6-part weapons (regular)
{
new[] { 4000, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 6000, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 10000, 0, 0, 0, 0, 0, 0, 0, 0 }
},
new[] // 6-part weapons (exceptional)
{
new[] { 7500, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 11250, 0, 0, 0, 0, 0, 0, 0, 0 },
new[] { 15000, 0, 0, 0, 0, 0, 0, 0, 0 }
}
};
private RewardType[] m_Types =
{
// Armors
new RewardType(200, typeof(RingmailGloves), typeof(RingmailChest), typeof(RingmailArms), typeof(RingmailLegs)),
new RewardType(300, typeof(ChainCoif), typeof(ChainLegs), typeof(ChainChest)),
new RewardType(400, typeof(PlateArms), typeof(PlateLegs), typeof(PlateHelm), typeof(PlateGorget),
typeof(PlateGloves), typeof(PlateChest)),
// Weapons
new RewardType(200, typeof(Bardiche), typeof(Halberd)),
new RewardType(300, typeof(Dagger), typeof(ShortSpear), typeof(Spear), typeof(WarFork),
typeof(Kryss)), //OSI put the dagger in there. Odd, ain't it.
new RewardType(350, typeof(Axe), typeof(BattleAxe), typeof(DoubleAxe), typeof(ExecutionersAxe),
typeof(LargeBattleAxe), typeof(TwoHandedAxe)),
new RewardType(350, typeof(Broadsword), typeof(Cutlass), typeof(Katana), typeof(Longsword),
typeof(Scimitar), /*typeof( ThinLongsword ),*/ typeof(VikingSword)),
new RewardType(350, typeof(WarAxe), typeof(HammerPick), typeof(Mace), typeof(Maul), typeof(WarHammer),
typeof(WarMace))
};
public SmithRewardCalculator()
{
Groups = new[]
{
new RewardGroup(0, new RewardItem(1, SturdyShovel)),
new RewardGroup(25, new RewardItem(1, SturdyPickaxe)),
new RewardGroup(50, new RewardItem(45, SturdyShovel), new RewardItem(45, SturdyPickaxe),
new RewardItem(10, MiningGloves, 1)),
new RewardGroup(200, new RewardItem(45, GargoylesPickaxe), new RewardItem(45, ProspectorsTool),
new RewardItem(10, MiningGloves, 3)),
new RewardGroup(400, new RewardItem(2, GargoylesPickaxe), new RewardItem(2, ProspectorsTool),
new RewardItem(1, PowderOfTemperament)),
new RewardGroup(450, new RewardItem(9, PowderOfTemperament), new RewardItem(1, MiningGloves, 5)),
new RewardGroup(500, new RewardItem(1, RunicHammer, 1)),
new RewardGroup(550, new RewardItem(3, RunicHammer, 1), new RewardItem(2, RunicHammer, 2)),
new RewardGroup(600, new RewardItem(1, RunicHammer, 2)),
new RewardGroup(625, new RewardItem(3, RunicHammer, 2), new RewardItem(6, PowerScroll, 5),
new RewardItem(1, ColoredAnvil)),
new RewardGroup(650, new RewardItem(1, RunicHammer, 3)),
new RewardGroup(675, new RewardItem(1, ColoredAnvil), new RewardItem(6, PowerScroll, 10),
new RewardItem(3, RunicHammer, 3)),
new RewardGroup(700, new RewardItem(1, RunicHammer, 4)),
new RewardGroup(750, new RewardItem(1, AncientHammer, 10)),
new RewardGroup(800, new RewardItem(1, PowerScroll, 15)),
new RewardGroup(850, new RewardItem(1, AncientHammer, 15)),
new RewardGroup(900, new RewardItem(1, PowerScroll, 20)),
new RewardGroup(950, new RewardItem(1, RunicHammer, 5)),
new RewardGroup(1000, new RewardItem(1, AncientHammer, 30)),
new RewardGroup(1050, new RewardItem(1, RunicHammer, 6)),
new RewardGroup(1100, new RewardItem(1, AncientHammer, 60)),
new RewardGroup(1150, new RewardItem(1, RunicHammer, 7)),
new RewardGroup(1200, new RewardItem(1, RunicHammer, 8))
};
}
public override int ComputePoints(int quantity, bool exceptional, BulkMaterialType material, int itemCount,
Type type)
{
int points = 0;
if (quantity == 10)
points += 10;
else if (quantity == 15)
points += 25;
else if (quantity == 20)
points += 50;
if (exceptional)
points += 200;
if (itemCount > 1)
points += LookupTypePoints(m_Types, type);
if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite)
points += 200 + 50 * (material - BulkMaterialType.DullCopper);
return points;
}
private int ComputeType(Type type, int itemCount)
{
// Item count of 1 means it's a small BOD.
if (itemCount == 1)
return 0;
int typeIdx = 0;
// Loop through the RewardTypes defined earlier and find the correct one.
for (; typeIdx < 7; ++typeIdx)
if (m_Types[typeIdx].Contains(type))
break;
// Types 5, 6 and 7 are Large Weapon BODs with the same rewards.
if (typeIdx > 5)
typeIdx = 5;
return (typeIdx + 1) * 2;
}
public override int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type)
{
int[][][] goldTable = m_GoldTable;
int typeIndex = ComputeType(type, itemCount);
int quanIndex = quantity == 20 ? 2 : quantity == 15 ? 1 : 0;
int mtrlIndex = material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite
? 1 + (material - BulkMaterialType.DullCopper)
: 0;
if (exceptional)
typeIndex++;
int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
int min = gold * 9 / 10;
int max = gold * 10 / 9;
return Utility.RandomMinMax(min, max);
}
#region Constructors
private static Item CreateSturdyShovel(int type)
{
return new SturdyShovel();
}
private static Item CreateSturdyPickaxe(int type)
{
return new SturdyPickaxe();
}
private static Item CreateMiningGloves(int type)
{
switch (type)
{
case 1:
return new LeatherGlovesOfMining(1);
case 3:
return new StuddedGlovesOfMining(3);
case 5:
return new RingmailGlovesOfMining(5);
default:
throw new InvalidOperationException();
}
}
private static Item CreateGargoylesPickaxe(int type)
{
return new GargoylesPickaxe();
}
private static Item CreateProspectorsTool(int type)
{
return new ProspectorsTool();
}
private static Item CreatePowderOfTemperament(int type)
{
return new PowderOfTemperament();
}
private static Item CreateRunicHammer(int type)
{
if (type >= 1 && type <= 8)
return new RunicHammer(CraftResource.Iron + type, Core.AOS ? 55 - type * 5 : 50);
throw new InvalidOperationException();
}
private static Item CreatePowerScroll(int type)
{
if (type == 5 || type == 10 || type == 15 || type == 20)
return new PowerScroll(SkillName.Blacksmith, 100 + type);
throw new InvalidOperationException();
}
private static Item CreateColoredAnvil(int type)
{
// Generate an anvil deed, not an actual anvil.
//return new ColoredAnvilDeed();
return new ColoredAnvil();
}
private static Item CreateAncientHammer(int type)
{
if (type == 10 || type == 15 || type == 30 || type == 60)
return new AncientSmithyHammer(type);
throw new InvalidOperationException();
}
#endregion
}
public sealed class TailorRewardCalculator : RewardCalculator
{
private static readonly ConstructCallback Cloth = CreateCloth;
private static readonly ConstructCallback Sandals = CreateSandals;
private static readonly ConstructCallback StretchedHide = CreateStretchedHide;
private static readonly ConstructCallback RunicKit = CreateRunicKit;
private static readonly ConstructCallback Tapestry = CreateTapestry;
private static readonly ConstructCallback PowerScroll = CreatePowerScroll;
private static readonly ConstructCallback BearRug = CreateBearRug;
private static readonly ConstructCallback ClothingBlessDeed = CreateCBD;
public static readonly TailorRewardCalculator Instance = new TailorRewardCalculator();
private static int[][][] m_AosGoldTable =
{
new[] // 1-part (regular)
{
new[] { 150, 150, 300, 300 },
new[] { 225, 225, 450, 450 },
new[] { 300, 400, 600, 750 }
},
new[] // 1-part (exceptional)
{
new[] { 300, 300, 600, 600 },
new[] { 450, 450, 900, 900 },
new[] { 600, 750, 1200, 1800 }
},
new[] // 4-part (regular)
{
new[] { 4000, 4000, 5000, 5000 },
new[] { 6000, 6000, 7500, 7500 },
new[] { 8000, 10000, 10000, 15000 }
},
new[] // 4-part (exceptional)
{
new[] { 5000, 5000, 7500, 7500 },
new[] { 7500, 7500, 11250, 11250 },
new[] { 10000, 15000, 15000, 20000 }
},
new[] // 5-part (regular)
{
new[] { 5000, 5000, 7500, 7500 },
new[] { 7500, 7500, 11250, 11250 },
new[] { 10000, 15000, 15000, 20000 }
},
new[] // 5-part (exceptional)
{
new[] { 7500, 7500, 10000, 10000 },
new[] { 11250, 11250, 15000, 15000 },
new[] { 15000, 20000, 20000, 30000 }
},
new[] // 6-part (regular)
{
new[] { 7500, 7500, 10000, 10000 },
new[] { 11250, 11250, 15000, 15000 },
new[] { 15000, 20000, 20000, 30000 }
},
new[] // 6-part (exceptional)
{
new[] { 10000, 10000, 15000, 15000 },
new[] { 15000, 15000, 22500, 22500 },
new[] { 20000, 30000, 30000, 50000 }
}
};
private static int[][][] m_OldGoldTable =
{
new[] // 1-part (regular)
{
new[] { 150, 150, 300, 300 },
new[] { 225, 225, 450, 450 },
new[] { 300, 400, 600, 750 }
},
new[] // 1-part (exceptional)
{
new[] { 300, 300, 600, 600 },
new[] { 450, 450, 900, 900 },
new[] { 600, 750, 1200, 1800 }
},
new[] // 4-part (regular)
{
new[] { 3000, 3000, 4000, 4000 },
new[] { 4500, 4500, 6000, 6000 },
new[] { 6000, 8000, 8000, 10000 }
},
new[] // 4-part (exceptional)
{
new[] { 4000, 4000, 5000, 5000 },
new[] { 6000, 6000, 7500, 7500 },
new[] { 8000, 10000, 10000, 15000 }
},
new[] // 5-part (regular)
{
new[] { 4000, 4000, 5000, 5000 },
new[] { 6000, 6000, 7500, 7500 },
new[] { 8000, 10000, 10000, 15000 }
},
new[] // 5-part (exceptional)
{
new[] { 5000, 5000, 7500, 7500 },
new[] { 7500, 7500, 11250, 11250 },
new[] { 10000, 15000, 15000, 20000 }
},
new[] // 6-part (regular)
{
new[] { 5000, 5000, 7500, 7500 },
new[] { 7500, 7500, 11250, 11250 },
new[] { 10000, 15000, 15000, 20000 }
},
new[] // 6-part (exceptional)
{
new[] { 7500, 7500, 10000, 10000 },
new[] { 11250, 11250, 15000, 15000 },
new[] { 15000, 20000, 20000, 30000 }
}
};
public TailorRewardCalculator()
{
Groups = new[]
{
new RewardGroup(0, new RewardItem(1, Cloth)),
new RewardGroup(50, new RewardItem(1, Cloth, 1)),
new RewardGroup(100, new RewardItem(1, Cloth, 2)),
new RewardGroup(150, new RewardItem(9, Cloth, 3), new RewardItem(1, Sandals)),
new RewardGroup(200, new RewardItem(4, Cloth, 4), new RewardItem(1, Sandals)),
new RewardGroup(300, new RewardItem(1, StretchedHide)),
new RewardGroup(350, new RewardItem(1, RunicKit, 1)),
new RewardGroup(400, new RewardItem(2, PowerScroll, 5), new RewardItem(3, Tapestry)),
new RewardGroup(450, new RewardItem(1, BearRug)),
new RewardGroup(500, new RewardItem(1, PowerScroll, 10)),
new RewardGroup(550, new RewardItem(1, ClothingBlessDeed)),
new RewardGroup(575, new RewardItem(1, PowerScroll, 15)),
new RewardGroup(600, new RewardItem(1, RunicKit, 2)),
new RewardGroup(650, new RewardItem(1, PowerScroll, 20)),
new RewardGroup(700, new RewardItem(1, RunicKit, 3))
};
}
public override int ComputePoints(int quantity, bool exceptional, BulkMaterialType material, int itemCount,
Type type)
{
int points = 0;
if (quantity == 10)
points += 10;
else if (quantity == 15)
points += 25;
else if (quantity == 20)
points += 50;
if (exceptional)
points += 100;
if (itemCount == 4)
points += 300;
else if (itemCount == 5)
points += 400;
else if (itemCount == 6)
points += 500;
if (material == BulkMaterialType.Spined)
points += 50;
else if (material == BulkMaterialType.Horned)
points += 100;
else if (material == BulkMaterialType.Barbed)
points += 150;
return points;
}
public override int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type)
{
int[][][] goldTable = Core.AOS ? m_AosGoldTable : m_OldGoldTable;
int typeIndex = (itemCount == 6 ? 3 : itemCount == 5 ? 2 : itemCount == 4 ? 1 : 0) * 2 + (exceptional ? 1 : 0);
int quanIndex = quantity == 20 ? 2 : quantity == 15 ? 1 : 0;
int mtrlIndex = material == BulkMaterialType.Barbed ? 3 :
material == BulkMaterialType.Horned ? 2 :
material == BulkMaterialType.Spined ? 1 : 0;
int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
int min = gold * 9 / 10;
int max = gold * 10 / 9;
return Utility.RandomMinMax(min, max);
}
#region Constructors
private static int[][] m_ClothHues =
{
new[] { 0x483, 0x48C, 0x488, 0x48A },
new[] { 0x495, 0x48B, 0x486, 0x485 },
new[] { 0x48D, 0x490, 0x48E, 0x491 },
new[] { 0x48F, 0x494, 0x484, 0x497 },
new[] { 0x489, 0x47F, 0x482, 0x47E }
};
private static Item CreateCloth(int type)
{
if (type >= 0 && type < m_ClothHues.Length)
{
UncutCloth cloth = new UncutCloth(100);
cloth.Hue = m_ClothHues[type][Utility.Random(m_ClothHues[type].Length)];
return cloth;
}
throw new InvalidOperationException();
}
private static int[] m_SandalHues =
{
0x489, 0x47F, 0x482,
0x47E, 0x48F, 0x494,
0x484, 0x497
};
private static Item CreateSandals(int type)
{
return new Sandals(m_SandalHues[Utility.Random(m_SandalHues.Length)]);
}
private static Item CreateStretchedHide(int type)
{
switch (Utility.Random(4))
{
default:
return new SmallStretchedHideEastDeed();
case 1: return new SmallStretchedHideSouthDeed();
case 2: return new MediumStretchedHideEastDeed();
case 3: return new MediumStretchedHideSouthDeed();
}
}
private static Item CreateTapestry(int type)
{
switch (Utility.Random(4))
{
default:
return new LightFlowerTapestryEastDeed();
case 1: return new LightFlowerTapestrySouthDeed();
case 2: return new DarkFlowerTapestryEastDeed();
case 3: return new DarkFlowerTapestrySouthDeed();
}
}
private static Item CreateBearRug(int type)
{
switch (Utility.Random(4))
{
default:
return new BrownBearRugEastDeed();
case 1: return new BrownBearRugSouthDeed();
case 2: return new PolarBearRugEastDeed();
case 3: return new PolarBearRugSouthDeed();
}
}
private static Item CreateRunicKit(int type)
{
if (type >= 1 && type <= 3)
return new RunicSewingKit(CraftResource.RegularLeather + type, 60 - type * 15);
throw new InvalidOperationException();
}
private static Item CreatePowerScroll(int type)
{
if (type == 5 || type == 10 || type == 15 || type == 20)
return new PowerScroll(SkillName.Tailoring, 100 + type);
throw new InvalidOperationException();
}
private static Item CreateCBD(int type)
{
return new ClothingBlessDeed();
}
#endregion
}
}

View file

@ -0,0 +1,213 @@
using System;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.BulkOrders
{
public abstract class SmallBOD : BaseBOD
{
private int m_AmountCur;
private int m_Number;
public SmallBOD(int hue, int amountCur, int amountMax, Type type, int number, int graphic, bool requireExeptional,
BulkMaterialType material) : base(hue, amountMax, requireExeptional, material)
{
Type = type;
Graphic = graphic;
m_AmountCur = amountCur;
m_Number = number;
}
public SmallBOD()
{
}
public SmallBOD(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public int AmountCur
{
get => m_AmountCur;
set
{
m_AmountCur = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public Type Type{ get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Number
{
get => m_Number;
set
{
m_Number = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int Graphic{ get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public override bool Complete => m_AmountCur == AmountMax;
public override int LabelNumber => 1045151; // a bulk order deed
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
list.Add(1060654); // small bulk order
if (RequireExceptional)
list.Add(1045141); // All items must be exceptional.
if (Material != BulkMaterialType.None)
list.Add(SmallBODGump.GetMaterialNumberFor(Material)); // All items must be made with x material.
list.Add(1060656, AmountMax.ToString()); // amount to make: ~1_val~
list.Add(1060658, "#{0}\t{1}", m_Number, m_AmountCur); // ~1_val~: ~2_val~
}
public override void OnDoubleClick(Mobile from)
{
if (IsChildOf(from.Backpack) || InSecureTrade || RootParent is PlayerVendor)
from.SendGump(new SmallBODGump(from, this));
else
from.SendLocalizedMessage(1045156); // You must have the deed in your backpack to use it.
}
public override void OnDoubleClickNotAccessible(Mobile from)
{
OnDoubleClick(from);
}
public override void OnDoubleClickSecureTrade(Mobile from)
{
OnDoubleClick(from);
}
public static BulkMaterialType GetMaterial(CraftResource resource)
{
switch (resource)
{
case CraftResource.DullCopper: return BulkMaterialType.DullCopper;
case CraftResource.ShadowIron: return BulkMaterialType.ShadowIron;
case CraftResource.Copper: return BulkMaterialType.Copper;
case CraftResource.Bronze: return BulkMaterialType.Bronze;
case CraftResource.Gold: return BulkMaterialType.Gold;
case CraftResource.Agapite: return BulkMaterialType.Agapite;
case CraftResource.Verite: return BulkMaterialType.Verite;
case CraftResource.Valorite: return BulkMaterialType.Valorite;
case CraftResource.SpinedLeather: return BulkMaterialType.Spined;
case CraftResource.HornedLeather: return BulkMaterialType.Horned;
case CraftResource.BarbedLeather: return BulkMaterialType.Barbed;
}
return BulkMaterialType.None;
}
public override void EndCombine(Mobile from, Item item)
{
Type objectType = item.GetType();
if (m_AmountCur >= AmountMax)
{
from.SendLocalizedMessage(
1045166); // The maximum amount of requested items have already been combined to this deed.
}
else if (Type == null || objectType != Type && !objectType.IsSubclassOf(Type) ||
!(item is BaseWeapon) && !(item is BaseArmor) && !(item is BaseClothing))
{
from.SendLocalizedMessage(1045169); // The item is not in the request.
}
else
{
BaseArmor armor = item as BaseArmor;
BaseClothing clothing = item as BaseClothing;
BulkMaterialType material = GetMaterial(armor?.Resource ?? clothing?.Resource ?? CraftResource.None);
if (Material >= BulkMaterialType.DullCopper && Material <= BulkMaterialType.Valorite &&
material != Material)
{
from.SendLocalizedMessage(1045168); // The item is not made from the requested ore.
}
else if (Material >= BulkMaterialType.Spined && Material <= BulkMaterialType.Barbed &&
material != Material)
{
from.SendLocalizedMessage(1049352); // The item is not made from the requested leather type.
}
else
{
bool isExceptional;
if (item is BaseWeapon weapon)
isExceptional = weapon.Quality == WeaponQuality.Exceptional;
else if (armor != null)
isExceptional = armor.Quality == ArmorQuality.Exceptional;
else
isExceptional = clothing.Quality == ClothingQuality.Exceptional;
if (RequireExceptional && !isExceptional)
{
from.SendLocalizedMessage(1045167); // The item must be exceptional.
}
else
{
item.Delete();
++AmountCur;
from.SendLocalizedMessage(1045170); // The item has been combined with the deed.
from.SendGump(new SmallBODGump(from, this));
if (m_AmountCur < AmountMax)
BeginCombine(from);
}
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(m_AmountCur);
writer.Write(Type == null ? null : Type.FullName);
writer.Write(m_Number);
writer.Write(Graphic);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_AmountCur = reader.ReadInt();
string type = reader.ReadString();
if (type != null)
Type = ScriptCompiler.FindTypeByFullName(type);
m_Number = reader.ReadInt();
Graphic = reader.ReadInt();
break;
}
}
}
}
}

View file

@ -0,0 +1,98 @@
using Server.Gumps;
using Server.Network;
namespace Server.Engines.BulkOrders
{
public class SmallBODAcceptGump : Gump
{
private SmallBOD m_Deed;
private Mobile m_From;
public SmallBODAcceptGump(Mobile from, SmallBOD deed) : base(50, 50)
{
m_From = from;
m_Deed = deed;
m_From.CloseGump<LargeBODAcceptGump>();
m_From.CloseGump<SmallBODAcceptGump>();
AddPage(0);
AddBackground(25, 10, 430, 264, 5054);
AddImageTiled(33, 20, 413, 245, 2624);
AddAlphaRegion(33, 20, 413, 245);
AddImage(20, 5, 10460);
AddImage(430, 5, 10460);
AddImage(20, 249, 10460);
AddImage(430, 249, 10460);
AddHtmlLocalized(190, 25, 120, 20, 1045133, 0x7FFF); // A bulk order
AddHtmlLocalized(40, 48, 350, 20, 1045135, 0x7FFF); // Ah! Thanks for the goods! Would you help me out?
AddHtmlLocalized(40, 72, 210, 20, 1045138, 0x7FFF); // Amount to make:
AddLabel(250, 72, 1152, deed.AmountMax.ToString());
AddHtmlLocalized(40, 96, 120, 20, 1045136, 0x7FFF); // Item requested:
AddItem(385, 96, deed.Graphic);
AddHtmlLocalized(40, 120, 210, 20, deed.Number, 0xFFFFFF);
if (deed.RequireExceptional || deed.Material != BulkMaterialType.None)
{
AddHtmlLocalized(40, 144, 210, 20, 1045140, 0x7FFF); // Special requirements to meet:
if (deed.RequireExceptional)
AddHtmlLocalized(40, 168, 350, 20, 1045141, 0x7FFF); // All items must be exceptional.
if (deed.Material != BulkMaterialType.None)
AddHtmlLocalized(40, deed.RequireExceptional ? 192 : 168, 350, 20, GetMaterialNumberFor(deed.Material),
0x7FFF); // All items must be made with x material.
}
AddHtmlLocalized(40, 216, 350, 20, 1045139, 0x7FFF); // Do you want to accept this order?
AddButton(100, 240, 4005, 4007, 1);
AddHtmlLocalized(135, 240, 120, 20, 1006044, 0x7FFF); // Ok
AddButton(275, 240, 4005, 4007, 0);
AddHtmlLocalized(310, 240, 120, 20, 1011012, 0x7FFF); // CANCEL
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID == 1) // Ok
{
if (m_From.PlaceInBackpack(m_Deed))
{
m_From.SendLocalizedMessage(1045152); // The bulk order deed has been placed in your backpack.
}
else
{
m_From.SendLocalizedMessage(1045150); // There is not enough room in your backpack for the deed.
m_Deed.Delete();
}
}
else
{
m_Deed.Delete();
}
}
public override void OnServerClose(NetState owner)
{
if (m_Deed?.Deleted == false)
m_Deed.Delete();
}
public static int GetMaterialNumberFor(BulkMaterialType material)
{
if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite)
return 1045142 + (material - BulkMaterialType.DullCopper);
if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed)
return 1049348 + (material - BulkMaterialType.Spined);
return 0;
}
}
}

View file

@ -0,0 +1,82 @@
using Server.Gumps;
using Server.Network;
namespace Server.Engines.BulkOrders
{
public class SmallBODGump : Gump
{
private SmallBOD m_Deed;
private Mobile m_From;
public SmallBODGump(Mobile from, SmallBOD deed) : base(25, 25)
{
m_From = from;
m_Deed = deed;
m_From.CloseGump<LargeBODGump>();
m_From.CloseGump<SmallBODGump>();
AddPage(0);
AddBackground(50, 10, 455, 260, 5054);
AddImageTiled(58, 20, 438, 241, 2624);
AddAlphaRegion(58, 20, 438, 241);
AddImage(45, 5, 10460);
AddImage(480, 5, 10460);
AddImage(45, 245, 10460);
AddImage(480, 245, 10460);
AddHtmlLocalized(225, 25, 120, 20, 1045133, 0x7FFF); // A bulk order
AddHtmlLocalized(75, 48, 250, 20, 1045138, 0x7FFF); // Amount to make:
AddLabel(275, 48, 1152, deed.AmountMax.ToString());
AddHtmlLocalized(275, 76, 200, 20, 1045153, 0x7FFF); // Amount finished:
AddHtmlLocalized(75, 72, 120, 20, 1045136, 0x7FFF); // Item requested:
AddItem(410, 72, deed.Graphic);
AddHtmlLocalized(75, 96, 210, 20, deed.Number, 0x7FFF);
AddLabel(275, 96, 0x480, deed.AmountCur.ToString());
if (deed.RequireExceptional || deed.Material != BulkMaterialType.None)
AddHtmlLocalized(75, 120, 200, 20, 1045140, 0x7FFF); // Special requirements to meet:
if (deed.RequireExceptional)
AddHtmlLocalized(75, 144, 300, 20, 1045141, 0x7FFF); // All items must be exceptional.
if (deed.Material != BulkMaterialType.None)
AddHtmlLocalized(75, deed.RequireExceptional ? 168 : 144, 300, 20, GetMaterialNumberFor(deed.Material),
0x7FFF); // All items must be made with x material.
AddButton(125, 192, 4005, 4007, 2);
AddHtmlLocalized(160, 192, 300, 20, 1045154, 0x7FFF); // Combine this deed with the item requested.
AddButton(125, 216, 4005, 4007, 1);
AddHtmlLocalized(160, 216, 120, 20, 1011441, 0x7FFF); // EXIT
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (m_Deed.Deleted || !m_Deed.IsChildOf(m_From.Backpack))
return;
if (info.ButtonID == 2) // Combine
{
m_From.SendGump(new SmallBODGump(m_From, m_Deed));
m_Deed.BeginCombine(m_From);
}
}
public static int GetMaterialNumberFor(BulkMaterialType material)
{
if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite)
return 1045142 + (material - BulkMaterialType.DullCopper);
if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed)
return 1049348 + (material - BulkMaterialType.Spined);
return 0;
}
}
}

View file

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Server.Engines.BulkOrders
{
public class SmallBulkEntry
{
public Type Type { get; }
public int Number { get; }
public int Graphic { get; }
public SmallBulkEntry( Type type, int number, int graphic )
{
Type = type;
Number = number;
Graphic = graphic;
}
public static SmallBulkEntry[] BlacksmithWeapons => GetEntries( "Blacksmith", "weapons" );
public static SmallBulkEntry[] BlacksmithArmor => GetEntries( "Blacksmith", "armor" );
public static SmallBulkEntry[] TailorCloth => GetEntries( "Tailoring", "cloth" );
public static SmallBulkEntry[] TailorLeather => GetEntries( "Tailoring", "leather" );
private static Dictionary<string, Dictionary<string, SmallBulkEntry[]>> m_Cache;
public static SmallBulkEntry[] GetEntries( string type, string name )
{
if ( m_Cache == null )
m_Cache = new Dictionary<string, Dictionary<string, SmallBulkEntry[]>>();
if (!m_Cache.TryGetValue( type, out Dictionary<string, SmallBulkEntry[]> table ))
m_Cache[type] = table = new Dictionary<string, SmallBulkEntry[]>();
if (!table.TryGetValue( name, out SmallBulkEntry[] entries ))
table[name] = entries = LoadEntries(type, name);
return entries;
}
public static SmallBulkEntry[] LoadEntries( string type, string name )
{
return LoadEntries($"Data/Bulk Orders/{type}/{name}.cfg");
}
public static SmallBulkEntry[] LoadEntries( string path )
{
path = Path.Combine( Core.BaseDirectory, path );
List<SmallBulkEntry> list = new List<SmallBulkEntry>();
if ( File.Exists( path ) )
{
using ( StreamReader ip = new StreamReader( path ) )
{
string line;
while ( (line = ip.ReadLine()) != null )
{
if ( line.Length == 0 || line.StartsWith( "#" ) )
continue;
try
{
string[] split = line.Split( '\t' );
if ( split.Length >= 2 )
{
Type type = ScriptCompiler.FindTypeByName( split[0] );
int graphic = Utility.ToInt32( split[split.Length - 1] );
if ( type != null && graphic > 0 )
list.Add( new SmallBulkEntry( type, graphic < 0x4000 ? 1020000 + graphic : 1078872 + graphic, graphic ) );
}
}
catch
{
// ignored
}
}
}
}
return list.ToArray();
}
}
}

View file

@ -0,0 +1,195 @@
using System;
using System.Collections.Generic;
using Server.Engines.Craft;
namespace Server.Engines.BulkOrders
{
public class SmallSmithBOD : SmallBOD
{
public static double[] m_BlacksmithMaterialChances =
{
0.501953125, // None
0.250000000, // Dull Copper
0.125000000, // Shadow Iron
0.062500000, // Copper
0.031250000, // Bronze
0.015625000, // Gold
0.007812500, // Agapite
0.003906250, // Verite
0.001953125 // Valorite
};
private SmallSmithBOD(SmallBulkEntry entry, BulkMaterialType mat, int amountMax, bool reqExceptional)
: base(0x44E, 0, amountMax, entry.Type, entry.Number, entry.Graphic, reqExceptional, mat)
{
}
[Constructible]
public SmallSmithBOD()
{
bool useMaterials = Utility.RandomBool();
SmallBulkEntry[] entries = useMaterials ? SmallBulkEntry.BlacksmithArmor :
SmallBulkEntry.BlacksmithWeapons;
if (entries.Length <= 0)
return;
int hue = 0x44E;
int amountMax = Utility.RandomList(10, 15, 20);
BulkMaterialType material = useMaterials ? GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances)
: BulkMaterialType.None;
bool reqExceptional = Utility.RandomBool() || material == BulkMaterialType.None;
SmallBulkEntry entry = entries[Utility.Random(entries.Length)];
Hue = hue;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
public SmallSmithBOD(int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional,
BulkMaterialType mat) : base(0x44E, amountCur, amountMax, type, number, graphic, reqExceptional, mat)
{
}
public SmallSmithBOD(Serial serial) : base(serial)
{
}
public override int ComputeFame() => SmithRewardCalculator.Instance.ComputeFame(this);
public override int ComputeGold() => SmithRewardCalculator.Instance.ComputeGold(this);
public override RewardGroup GetRewardGroup() =>
SmithRewardCalculator.Instance.LookupRewards(SmithRewardCalculator.Instance.ComputePoints(this));
public static SmallSmithBOD CreateRandomFor(Mobile m)
{
bool useMaterials = Utility.RandomBool();
SmallBulkEntry[] entries = useMaterials ? SmallBulkEntry.BlacksmithArmor :
SmallBulkEntry.BlacksmithWeapons;
if (entries.Length <= 0)
return null;
double theirSkill = m.Skills.Blacksmith.Base;
int amountMax;
if (theirSkill >= 70.1)
amountMax = Utility.RandomList(10, 15, 20, 20);
else if (theirSkill >= 50.1)
amountMax = Utility.RandomList(10, 15, 15, 20);
else
amountMax = Utility.RandomList(10, 10, 15, 20);
BulkMaterialType material = BulkMaterialType.None;
if (useMaterials && theirSkill >= 70.1)
for (int i = 0; i < 20; ++i)
{
BulkMaterialType check = GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances);
double skillReq = 0.0;
switch (check)
{
case BulkMaterialType.DullCopper:
skillReq = 65.0;
break;
case BulkMaterialType.ShadowIron:
skillReq = 70.0;
break;
case BulkMaterialType.Copper:
skillReq = 75.0;
break;
case BulkMaterialType.Bronze:
skillReq = 80.0;
break;
case BulkMaterialType.Gold:
skillReq = 85.0;
break;
case BulkMaterialType.Agapite:
skillReq = 90.0;
break;
case BulkMaterialType.Verite:
skillReq = 95.0;
break;
case BulkMaterialType.Valorite:
skillReq = 100.0;
break;
case BulkMaterialType.Spined:
skillReq = 65.0;
break;
case BulkMaterialType.Horned:
skillReq = 80.0;
break;
case BulkMaterialType.Barbed:
skillReq = 99.0;
break;
}
if (theirSkill >= skillReq)
{
material = check;
break;
}
}
double excChance = theirSkill >= 70.1 ? (theirSkill + 80.0) / 200.0 : 0.0;
bool reqExceptional = excChance > Utility.RandomDouble();
CraftSystem system = DefBlacksmithy.CraftSystem;
List<SmallBulkEntry> validEntries = new List<SmallBulkEntry>();
for (int i = 0; i < entries.Length; ++i)
{
CraftItem item = system.CraftItems.SearchFor(entries[i].Type);
if (item != null)
{
bool allRequiredSkills = true;
double chance = item.GetSuccessChance(m, null, system, false, ref allRequiredSkills);
if (allRequiredSkills && chance >= 0.0)
{
if (reqExceptional)
chance = item.GetExceptionalChance(system, chance, m);
if (chance > 0.0)
validEntries.Add(entries[i]);
}
}
}
if (validEntries.Count <= 0)
return null;
SmallBulkEntry entry = validEntries[Utility.Random(validEntries.Count)];
return new SmallSmithBOD(entry, material, amountMax, reqExceptional);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,191 @@
using System;
using System.Collections.Generic;
using Server.Engines.Craft;
namespace Server.Engines.BulkOrders
{
public class SmallTailorBOD : SmallBOD
{
public static double[] m_TailoringMaterialChances =
{
0.857421875, // None
0.125000000, // Spined
0.015625000, // Horned
0.001953125 // Barbed
};
private SmallTailorBOD(SmallBulkEntry entry, BulkMaterialType mat, int amountMax, bool reqExceptional)
: base(0x483, 0, amountMax, entry.Type, entry.Number, entry.Graphic, reqExceptional, mat)
{
}
[Constructible]
public SmallTailorBOD()
{
bool useMaterials = Utility.RandomBool();
SmallBulkEntry[] entries = useMaterials ? SmallBulkEntry.TailorLeather : SmallBulkEntry.TailorCloth;
if (entries.Length <= 0)
return;
int hue = 0x483;
int amountMax = Utility.RandomList(10, 15, 20);
BulkMaterialType material = useMaterials ? GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances)
: BulkMaterialType.None;
bool reqExceptional = Utility.RandomBool() || material == BulkMaterialType.None;
SmallBulkEntry entry = entries[Utility.Random(entries.Length)];
Hue = hue;
AmountMax = amountMax;
Type = entry.Type;
Number = entry.Number;
Graphic = entry.Graphic;
RequireExceptional = reqExceptional;
Material = material;
}
public SmallTailorBOD(int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional,
BulkMaterialType mat) : base(0x483, amountCur, amountMax, type, number, graphic, reqExceptional, mat)
{
}
public SmallTailorBOD(Serial serial) : base(serial)
{
}
public override int ComputeFame() => TailorRewardCalculator.Instance.ComputeFame(this);
public override int ComputeGold() => TailorRewardCalculator.Instance.ComputeGold(this);
public override RewardGroup GetRewardGroup() =>
TailorRewardCalculator.Instance.LookupRewards(TailorRewardCalculator.Instance.ComputePoints(this));
public static SmallTailorBOD CreateRandomFor(Mobile m)
{
SmallBulkEntry[] entries;
bool useMaterials = Utility.RandomBool();
double theirSkill = m.Skills.Tailoring.Base;
// Ugly, but the easiest leather BOD is Leather Cap which requires at least 6.2 skill.
if (useMaterials && theirSkill >= 6.2)
entries = SmallBulkEntry.TailorLeather;
else
entries = SmallBulkEntry.TailorCloth;
if (entries.Length > 0)
{
int amountMax;
if (theirSkill >= 70.1)
amountMax = Utility.RandomList(10, 15, 20, 20);
else if (theirSkill >= 50.1)
amountMax = Utility.RandomList(10, 15, 15, 20);
else
amountMax = Utility.RandomList(10, 10, 15, 20);
BulkMaterialType material = BulkMaterialType.None;
if (useMaterials && theirSkill >= 70.1)
for (int i = 0; i < 20; ++i)
{
BulkMaterialType check = GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances);
double skillReq = 0.0;
switch (check)
{
case BulkMaterialType.DullCopper:
skillReq = 65.0;
break;
case BulkMaterialType.Bronze:
skillReq = 80.0;
break;
case BulkMaterialType.Gold:
skillReq = 85.0;
break;
case BulkMaterialType.Agapite:
skillReq = 90.0;
break;
case BulkMaterialType.Verite:
skillReq = 95.0;
break;
case BulkMaterialType.Valorite:
skillReq = 100.0;
break;
case BulkMaterialType.Spined:
skillReq = 65.0;
break;
case BulkMaterialType.Horned:
skillReq = 80.0;
break;
case BulkMaterialType.Barbed:
skillReq = 99.0;
break;
}
if (theirSkill >= skillReq)
{
material = check;
break;
}
}
double excChance = 0.0;
if (theirSkill >= 70.1)
excChance = (theirSkill + 80.0) / 200.0;
bool reqExceptional = excChance > Utility.RandomDouble();
CraftSystem system = DefTailoring.CraftSystem;
List<SmallBulkEntry> validEntries = new List<SmallBulkEntry>();
for (int i = 0; i < entries.Length; ++i)
{
CraftItem item = system.CraftItems.SearchFor(entries[i].Type);
if (item != null)
{
bool allRequiredSkills = true;
double chance = item.GetSuccessChance(m, null, system, false, ref allRequiredSkills);
if (allRequiredSkills && chance >= 0.0)
{
if (reqExceptional)
chance = item.GetExceptionalChance(system, chance, m);
if (chance > 0.0)
validEntries.Add(entries[i]);
}
}
}
if (validEntries.Count > 0)
{
SmallBulkEntry entry = validEntries[Utility.Random(validEntries.Count)];
return new SmallTailorBOD(entry, material, amountMax, reqExceptional);
}
}
return null;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}