ModernUO/Projects/UOContent/Items/DungeonTreasure/BaseDungeonTreasure.cs

388 lines
13 KiB
C#

using System;
using ModernUO.Serialization;
using Server.Items;
namespace Server.Custom
{
// ==========================================
// 1. THE LOW-TIER BAG (Unlocked, Trapped, Tiers 0-3)
// ==========================================
[SerializationGenerator(0, false)]
public partial class DungeonLootBag : BaseDungeonTreasure
{
private static readonly (int, int)[] _appearances =
{
(0xE76, 0x3D), // Bag
(0xE75, 0x3C), // Backpack
(0xFFBA, 0x3C), // Backpack
(0xFFB9, 0x3C), // Backpack
(0xFFA6, 0x3C), // Backpack
(0xFFA5, 0x3C), // Backpack
(0xE79, 0x41) // Pouch
};
[Constructible]
public DungeonLootBag() : base(0xE76)
{
Name = "a discarded loot bag";
(ItemID, GumpID) = _appearances.RandomElement();
// Roll until we get a tier between 0 and 3
int tier;
do { tier = GetWeightedTier(); } while (tier < 0 || tier > 3);
MasterTier = tier;
// Security
Locked = false;
SetupTrap();
// Generate
GenerateLoot();
}
public DungeonLootBag(Serial serial) : base(serial) { }
}
// ==========================================
// 2. THE HIGH-TIER CRATE (Locked, Trapped, Tiers 3-6)
// ==========================================
[SerializationGenerator(0, false)]
public partial class DungeonLootCrate : BaseDungeonTreasure
{
private static readonly (int, int)[] _appearances =
{
(0x9A9, 0x44), // Small Crate
(0xE3F, 0x44), // Medium Crate
(0xE3D, 0x44), // Large Crate
(0x9A8, 0x4B), // Metal Box
(0xE43, 0x49), // Wooden Chest
(0xE77, 0x3E), // Barrel
(0x9AA, 0x43) // Wooden Box
};
[Constructible]
public DungeonLootCrate() : base(0x9A9)
{
Name = "a secured dungeon crate";
(ItemID, GumpID) = _appearances.RandomElement();
// Roll until we get a tier between 3 and 6
int tier;
do { tier = GetWeightedTier(); } while (tier < 3 || tier > 6);
MasterTier = tier;
// Security
Locked = true;
LockLevel = 50 + (MasterTier * 10);
MaxLockLevel = LockLevel + 25;
RequiredSkill = LockLevel;
SetupTrap();
// Generate
GenerateLoot();
}
public DungeonLootCrate(Serial serial) : base(serial) { }
}
// ==========================================
// 3. THE ABSTRACT BASE BLUEPRINT
// ==========================================
[SerializationGenerator(0, false)]
public abstract partial class BaseDungeonTreasure : LockableContainer
{
[SerializableField(0)]
private int m_MasterTier;
public BaseDungeonTreasure(int itemID) : base(itemID)
{
Movable = false;
Hue = Utility.Random(1, 1000);
}
public BaseDungeonTreasure(Serial serial) : base(serial) { }
public override bool Decays => true;
public override bool IsDecoContainer => false;
private readonly TimeSpan _decayTime = TimeSpan.FromMinutes(Utility.RandomMinMax(45, 60));
public override TimeSpan DecayTime => _decayTime;
public override Rectangle2D Bounds
{
get
{
if (GumpID == 0x3D) return new Rectangle2D(29, 34, 108, 94);
if (GumpID == 0x3C) return new Rectangle2D(44, 65, 142, 94);
if (GumpID == 0x41) return new Rectangle2D(35, 38, 110, 78);
if (GumpID == 0x44) return new Rectangle2D(20, 10, 150, 90);
if (GumpID == 0x4B) return new Rectangle2D(16, 51, 168, 73);
if (GumpID == 0x49) return new Rectangle2D(18, 105, 144, 73);
if (GumpID == 0x3E) return new Rectangle2D(33, 36, 109, 112);
if (GumpID == 0x9AA) return new Rectangle2D(16, 51, 168, 73);
return new Rectangle2D(18, 20, 125, 62);
}
}
protected void SetupTrap()
{
// Core UO Traps: 1 = Dart, 2 = Poison, 3 = Explosion, 4 = Magic
TrapType = (TrapType)Utility.RandomMinMax(1, 4);
TrapPower = 10 + (MasterTier * 15); // Scales damage/poison level with the tier
TrapLevel = MasterTier;
}
protected static int GetWeightedTier()
{
var roll = Utility.Random(100);
if (roll < 25) return 0;
else if (roll < 55) return 1;
else if (roll < 75) return 2;
else if (roll < 90) return 3;
else if (roll < 96) return 4;
else if (roll < 99) return 5;
else return 6;
}
private static void GetRandomLevel(int pwr, out int attributeCount, out int min, out int max)
{
if (pwr == 1)
{
attributeCount = 1;
min = 10;
max = 20;
}
else if (pwr == 2)
{
attributeCount = Utility.RandomMinMax(1, 2);
min = 20;
max = 40;
}
else if (pwr == 3)
{
attributeCount = Utility.RandomMinMax(2, 3);
min = 30;
max = 60;
}
else if (pwr == 4)
{
attributeCount = Utility.RandomMinMax(2, 4);
min = 40;
max = 80;
}
else if (pwr == 5)
{
attributeCount = Utility.RandomMinMax(3, 5);
min = 60;
max = 80;
}
else if (pwr == 6)
{
attributeCount = Utility.RandomMinMax(4, 5);
min = 60;
max = 100;
}
else
{
attributeCount = 1;
min = 5;
max = 10;
}
}
private static void GetRandomResists(int pwr, out int phy, out int fire, out int cold, out int poison, out int energy)
{
if (pwr == 1)
{
phy = Utility.RandomMinMax(1, 3);
fire = Utility.RandomMinMax(1, 3);
cold = Utility.RandomMinMax(1, 3);
poison = Utility.RandomMinMax(1, 3);
energy = Utility.RandomMinMax(1, 3);
}
else if (pwr == 2)
{
phy = Utility.RandomMinMax(2, 5);
fire = Utility.RandomMinMax(2, 5);
cold = Utility.RandomMinMax(2, 5);
poison = Utility.RandomMinMax(2, 5);
energy = Utility.RandomMinMax(2, 5);
}
else if (pwr == 3)
{
phy = Utility.RandomMinMax(4, 7);
fire = Utility.RandomMinMax(4, 7);
cold = Utility.RandomMinMax(4, 7);
poison = Utility.RandomMinMax(4, 7);
energy = Utility.RandomMinMax(4, 7);
}
else if (pwr == 4)
{
phy = Utility.RandomMinMax(6, 10);
fire = Utility.RandomMinMax(6, 10);
cold = Utility.RandomMinMax(6, 10);
poison = Utility.RandomMinMax(6, 10);
energy = Utility.RandomMinMax(6, 10);
}
else if (pwr == 5)
{
phy = Utility.RandomMinMax(9, 12);
fire = Utility.RandomMinMax(9, 12);
cold = Utility.RandomMinMax(9, 12);
poison = Utility.RandomMinMax(9, 12);
energy = Utility.RandomMinMax(9, 12);
}
else if (pwr == 6)
{
phy = Utility.RandomMinMax(12, 15);
fire = Utility.RandomMinMax(12, 15);
cold = Utility.RandomMinMax(12, 15);
poison = Utility.RandomMinMax(12, 15);
energy = Utility.RandomMinMax(12, 15);
}
else
{
phy = 0;
fire = 0;
cold = 0;
poison = 0;
energy = 0;
}
}
protected void GenerateLoot()
{
int dropCount = Utility.RandomMinMax(Math.Max(1, MasterTier -2), MasterTier + 1);
// Weapons
for (var i = 0; i < dropCount; i++)
{
var weapon = Loot.RandomWeapon();
int itemPower = Utility.RandomMinMax(0, MasterTier);
GetRandomLevel(itemPower, out var attributeCount, out var min, out var max);
BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max);
DropItem(weapon);
}
// Armor or Shield
for (var i = 0; i < dropCount; i++)
{
var armor = Loot.RandomArmorOrShield();
// Roll #1: Determines the magical properties (Attributes)
int attributePower = Utility.RandomMinMax(0, MasterTier);
GetRandomLevel(attributePower, out var attributeCount, out var min, out var max);
BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max);
// Roll #2: Determines the physical/elemental defense (Resists)
int resistPower = Utility.RandomMinMax(0, MasterTier);
GetRandomResists(resistPower, out var phy, out var fire, out var cold, out var poison, out var energy);
armor.PhysicalBonus = phy;
armor.FireBonus = fire;
armor.ColdBonus = cold;
armor.PoisonBonus = poison;
armor.EnergyBonus = energy;
DropItem(armor);
}
// Jewelry
for (var i = 0; i < dropCount; i++)
{
var jewelry = Loot.RandomJewelry();
int itemPower = Utility.RandomMinMax(0, MasterTier);
GetRandomLevel(itemPower, out var attributeCount, out var min, out var max);
BaseRunicTool.ApplyAttributesTo(jewelry, attributeCount, min, max);
DropItem(jewelry);
}
// Gems
for (var i = 0; i < dropCount; i++)
{
var gem = Loot.RandomGem();
gem.Amount = Utility.RandomMinMax(1, dropCount);
DropItem(gem);
}
// Reagents
for (var i = 0; i < dropCount; i++)
{
var mReagent = Loot.RandomReagent();
mReagent.Amount = Utility.RandomMinMax(1, dropCount);
DropItem(mReagent);
}
for (var i = 0; i < dropCount; i++)
{
var nReagent = Loot.RandomNecromancyReagent();
nReagent.Amount = Utility.RandomMinMax(1, dropCount);
DropItem(nReagent);
}
// Magic Scrolls
int mlevel = 0;
if (MasterTier >= 4)
{
mlevel = 63;
}
else if (MasterTier >= 2)
{
mlevel = 46;
}
else
{
mlevel = 23;
}
for (var i = 0; i < dropCount; i++)
{
var mscroll = Loot.RandomScroll(0, mlevel, SpellbookType.Regular);
mscroll.Amount = Utility.RandomMinMax(1, 3);
DropItem(mscroll);
}
int nlevel = 0;
if (MasterTier < 3)
{
nlevel = 7;
}
else
{
nlevel = 15;
}
for (var i = 0; i < dropCount; i++)
{
var nscroll = Loot.RandomScroll(0, nlevel, SpellbookType.Necromancer);
nscroll.Amount = Utility.RandomMinMax(1, 3);
DropItem(nscroll);
}
// Misc extras bandages/arrows/blankscrolls/potions/ETC
if (Utility.RandomBool())
{
DropItem(new Arrow(Utility.RandomMinMax(10, dropCount * 10)));
}
else
{
DropItem(new Bolt(Utility.RandomMinMax(10, dropCount * 10)));
}
if (Utility.RandomBool())
DropItem(new Bandage(Utility.RandomMinMax(10, dropCount * 10)));
if (Utility.RandomBool())
DropItem(new BlankScroll(Utility.RandomMinMax(1, dropCount)));
for (var i = 0; i < dropCount; i++)
{
var potion = Loot.RandomPotion();
potion.Amount = Utility.RandomMinMax(1, 3);
DropItem(potion);
}
if (Utility.RandomBool())
DropItem(new RecallRune());
// Gold
int minGold = 100 + (MasterTier * 100);
DropItem(new Gold(Utility.RandomMinMax(minGold, minGold + 99)));
}
}
}