#W# Treasure: DungeonBags/Crates. Bags are trapped level 0-3 loot. Crates are trapped and locked with level 4-6 loot.

This commit is contained in:
WarrentyExpired 2026-10-26 12:26:54 -04:00
parent 9704edebc9
commit aedf8d276f
11 changed files with 626 additions and 650 deletions

View file

@ -1,49 +0,0 @@
using System;
using ModernUO.Serialization;
using Server.Items;
namespace Server.Items;
public abstract class BaseTreasureBag : LockableContainer
{
public BaseTreasureBag() : base(0xE76)
{
SetBagAppearance();
Movable = false;
// Pick a random hue between 1 and 1000
Hue = Utility.Random(1, 1000);
}
public BaseTreasureBag(Serial serial) : base(serial)
{
}
public override bool Decays => true;
public override bool IsDecoContainer => false;
private readonly TimeSpan _decayTime = TimeSpan.FromMinutes(Utility.Random(15, 60));
public override TimeSpan DecayTime => _decayTime;
private static readonly (int, int)[] _bagAppearances =
{
(0xE76, 0x3D), // Bag
(0xE75, 0x3C), // Backpack
(0xE79, 0x41) // Pouch
};
private void SetBagAppearance()
{
(ItemID, GumpID) = _bagAppearances.RandomElement();
}
public override Rectangle2D Bounds
{
get
{
if (GumpID == 0x3D) return new Rectangle2D(29, 34, 108, 94); // Bag
if (GumpID == 0x3C) return new Rectangle2D(44, 65, 142, 94); // Backpack
return new Rectangle2D(18, 20, 125, 62); // Pouch
}
}
}

View file

@ -1,166 +0,0 @@
using System;
using ModernUO.Serialization;
namespace Server.Items;
[SerializationGenerator(0, false)]
public partial class RandomLootBag : Bag
{
private static int GetWeightedTier()
{
var roll = Utility.Random(100);
if (roll < 25) return 0; // 25% chance (Rolls 0-24)
else if (roll < 55) return 1; // 30% chance (Rolls 25-54)
else if (roll < 75) return 2; // 20% chance (Rolls 55-74)
else if (roll < 90) return 3; // 15% chance (Rolls 75-89)
else if (roll < 96) return 4; // 6% chance (Rolls 90-95)
else if (roll < 99) return 5; // 3% chance (Rolls 96-98)
else return 6; // 1% chance (Rolls 99)
}
private static void GetRandomLevel(out int attributeCount, out int min, out int max)
{
var pwr = GetWeightedTier();
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(out int phy, out int fire, out int cold, out int poison, out int energy)
{
var pwr = GetWeightedTier();
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;
}
}
[Constructible]
public RandomLootBag()
{
for (var i = Utility.Random(10) + 1; i > 0; i--)
{
var weapon = Loot.RandomWeapon();
GetRandomLevel(out var attributeCount, out var min, out var max);
BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max);
DropItem(weapon);
}
for ( var i = Utility.Random(10) + 1; i > 0; i--)
{
var armor = Loot.RandomArmorOrShield();
GetRandomLevel(out var attributeCount, out var min, out var max);
BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max);
GetRandomResists(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);
}
for (var i = Utility.Random(10) + 1; i > 0; i--)
{
var jewelry = Loot.RandomJewelry();
GetRandomLevel(out var attributeCount, out var min, out var max);
BaseRunicTool.ApplyAttributesTo(jewelry, attributeCount, min, max);
DropItem(jewelry);
}
}
}

View file

@ -1,76 +0,0 @@
using System;
using ModernUO.Serialization;
namespace Server.Items;
// ==============================================================
// LEVEL 1: 50% Trapped / 50% Locked
// ==============================================================
[SerializationGenerator(0, false)]
public partial class TreasureBagLevel1 : BaseTreasureBag
{
[Constructible]
public TreasureBagLevel1()
{
var isTrapped = false;
Locked = Utility.RandomDouble() < 0.50; // 50% Locked
RequiredSkill = 57;
LockLevel = RequiredSkill - Utility.Random(1, 10);
MaxLockLevel = RequiredSkill + Utility.Random(1, 10);
if (Utility.RandomDouble() < 0.50) // 50% Trapped
{
TrapType = TrapType.DartTrap;
TrapPower = Utility.Random(1, 25);
isTrapped = true;
}
if (isTrapped && Locked)
{
DropItem(new Gold(Utility.Random(30, 100)));
if (Utility.RandomBool())
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 3);
DropItem(gems);
}
if (Utility.RandomBool()) DropItem(Loot.RandomWeapon());
if (Utility.RandomBool()) DropItem(Loot.RandomArmorOrShield());
if (Utility.RandomBool()) DropItem(Loot.RandomClothing());
if (Utility.RandomBool()) DropItem(Loot.RandomJewelry());
}
else if (isTrapped && !Locked)
{
DropItem(new Gold(Utility.Random(30, 80)));
if (Utility.RandomBool())
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 3);
DropItem(gems);
}
if (Utility.RandomBool()) DropItem(Loot.RandomWeapon());
if (Utility.RandomBool()) DropItem(Loot.RandomClothing());
}
else if (!isTrapped && Locked)
{
DropItem(new Gold(Utility.Random(30, 80)));
if (Utility.RandomBool())
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 3);
DropItem(gems);
}
if (Utility.RandomBool()) DropItem(Loot.RandomArmor());
}
else
{
DropItem(new Gold(Utility.Random(30, 50)));
if (Utility.RandomBool())
{
var gems = Loot.RandomGem();
gems.Amount = 1;
DropItem(gems);
}
}
}
}

View file

@ -1,104 +0,0 @@
using System;
using ModernUO.Serialization;
namespace Server.Items;
// ==============================================================
// LEVEL 2: 75% Trapped / 75% Locked
// ==============================================================
[SerializationGenerator(0, false)]
public partial class TreasureBagLevel2 : BaseTreasureBag
{
[Constructible]
public TreasureBagLevel2()
{
Locked = Utility.RandomDouble() < 0.75; // 75% Locked (25% Unlocked)
RequiredSkill = 72;
LockLevel = RequiredSkill - Utility.Random(1, 10);
MaxLockLevel = RequiredSkill + Utility.Random(1, 10);
var isTrapped = false;
if (Utility.RandomDouble() < 0.75) // 75% Trapped
{
TrapType = TrapType.ExplosionTrap;
TrapPower = 2 * Utility.Random(1, 25);
isTrapped = true;
}
if (Locked && isTrapped)
{
DropItem(new Gold(Utility.Random(80, 150)));
for (var i = Utility.Random(3); i > 0; i--)
{
var reagents = Loot.RandomReagent();
reagents.Amount = Utility.Random(1, 2);
DropItem(reagents);
}
if (Utility.RandomBool())
{
var scrolls = Loot.RandomScroll(0, 39, SpellbookType.Regular);
scrolls.Amount = Utility.Random(1, 8);
DropItem(scrolls);
}
if (Utility.RandomBool())
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 6);
DropItem(gems);
}
if (Utility.RandomBool()) DropItem(Loot.RandomPotion());
}
else if (isTrapped && !Locked)
{
DropItem(new Gold(Utility.Random(80, 120)));
for (var i = Utility.Random(3); i > 0; i--)
{
var reagents = Loot.RandomReagent();
reagents.Amount = Utility.Random(1, 2);
DropItem(reagents);
}
if (Utility.RandomBool())
{
var scrolls = Loot.RandomScroll(0, 39, SpellbookType.Regular);
scrolls.Amount = Utility.Random(1, 4);
DropItem(scrolls);
}
if (Utility.RandomBool())
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 3);
DropItem(gems);
}
if (Utility.RandomBool()) DropItem(Loot.RandomPotion());
}
else if (!isTrapped && Locked)
{
DropItem(new Gold(Utility.Random(80, 120)));
for (var i = Utility.Random(3); i > 0; i--)
{
var reagents = Loot.RandomReagent();
reagents.Amount = Utility.Random(1, 2);
DropItem(reagents);
}
if (Utility.RandomBool())
{
var scrolls = Loot.RandomScroll(0, 39, SpellbookType.Regular);
scrolls.Amount = Utility.Random(1, 4);
DropItem(scrolls);
}
if (Utility.RandomBool())
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 3);
DropItem(gems);
}
if (Utility.RandomBool()) DropItem(Loot.RandomPotion());
}
else
{
DropItem(new Gold(Utility.Random(80, 100)));
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 3);
DropItem(gems);
}
}
}

View file

@ -1,281 +0,0 @@
using System;
using ModernUO.Serialization;
namespace Server.Items;
// ==============================================================
// LEVEL 3: 90% Trapped / 90% Locked
// ==============================================================
[SerializationGenerator(0, false)]
public partial class TreasureBagLevel3 : BaseTreasureBag
{
[Constructible]
public TreasureBagLevel3()
{
Locked = Utility.RandomDouble() < 0.90; // 90% Locked (10% Unlocked)
RequiredSkill = 84;
LockLevel = RequiredSkill - Utility.Random(1, 10);
MaxLockLevel = RequiredSkill + Utility.Random(1, 10);
var isTrapped = false;
if (Utility.RandomDouble() < 0.90) // 90% Trapped
{
TrapType = TrapType.PoisonTrap;
TrapPower = 3 * Utility.Random(1, 25);
isTrapped = true;
}
if (isTrapped && Locked)
{
DropItem(new Gold(Utility.Random(250, 350)));
for (var i = Utility.Random(2); i >= 0; i--)
{
var reagents = Loot.RandomReagent();
reagents.Amount = Utility.Random(1, 9);
DropItem(reagents);
}
for (var i = Utility.Random(3); i > 0; i--)
{
var scrolls = Loot.RandomScroll(0, 47, SpellbookType.Regular);
scrolls.Amount = Utility.Random(1, 12);
DropItem(scrolls);
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomPotion());
}
for (var i = Utility.Random(3); i > 0; i--)
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 9);
DropItem(gems);
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomWand());
}
for (var i = Utility.Random(3); i > 0; i--)
{
var item = Loot.RandomArmorOrShieldOrWeapon();
if (item is BaseWeapon weapon)
{
weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(3);
weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(3);
weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(3);
weapon.Quality = WeaponQuality.Regular;
}
else if (item is BaseArmor armor)
{
armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(3);
armor.Durability = (ArmorDurabilityLevel)Utility.Random(3);
armor.Quality = ArmorQuality.Regular;
}
DropItem(item);
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomClothing());
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomJewelry());
}
}
else if (!isTrapped && Locked)
{
DropItem(new Gold(Utility.Random(250, 300)));
for (var i = Utility.Random(2); i >= 0; i--)
{
var reagents = Loot.RandomReagent();
reagents.Amount = Utility.Random(1, 9);
DropItem(reagents);
}
for (var i = Utility.Random(3); i > 0; i--)
{
var scrolls = Loot.RandomScroll(0, 47, SpellbookType.Regular);
scrolls.Amount = Utility.Random(1, 12);
DropItem(scrolls);
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomPotion());
}
for (var i = Utility.Random(3); i > 0; i--)
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 9);
DropItem(gems);
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomWand());
}
if (Utility.RandomBool())
{
for (var i = Utility.Random(3); i > 0; i--)
{
var weapon = Loot.RandomWeapon();
weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(3);
weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(3);
weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(3);
weapon.Quality = WeaponQuality.Regular;
DropItem(weapon);
}
}
if (Utility.RandomBool())
{
for (var i = Utility.Random(3); i > 0; i--)
{
var armor = Loot.RandomArmorOrShield();
armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(3);
armor.Durability = (ArmorDurabilityLevel)Utility.Random(3);
armor.Quality = ArmorQuality.Regular;
DropItem(armor);
}
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomClothing());
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomJewelry());
}
}
else if (isTrapped && !Locked)
{
DropItem(new Gold(Utility.Random(250, 300)));
for (var i = Utility.Random(2); i >= 0; i--)
{
var reagents = Loot.RandomReagent();
reagents.Amount = Utility.Random(1, 4);
DropItem(reagents);
}
for (var i = Utility.Random(3); i > 0; i--)
{
var scrolls = Loot.RandomScroll(0, 47, SpellbookType.Regular);
scrolls.Amount = Utility.Random(1, 6);
DropItem(scrolls);
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomPotion());
}
for (var i = Utility.Random(3); i > 0; i--)
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 4);
DropItem(gems);
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomWand());
}
if (Utility.RandomBool())
{
if (Utility.RandomBool())
{
for (var i = Utility.Random(3); i > 0; i--)
{
var weapon = Loot.RandomWeapon();
weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(3);
weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(3);
weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(3);
weapon.Quality = WeaponQuality.Regular;
DropItem(weapon);
}
}
if (Utility.RandomBool())
{
for (var i = Utility.Random(3); i > 0; i--)
{
var armor = Loot.RandomArmorOrShield();
armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(3);
armor.Durability = (ArmorDurabilityLevel)Utility.Random(3);
armor.Quality = ArmorQuality.Regular;
DropItem(armor);
}
}
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomClothing());
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomJewelry());
}
}
else
{
DropItem(new Gold(Utility.Random(175, 225)));
for (var i = Utility.Random(2); i >= 0; i--)
{
var reagents = Loot.RandomReagent();
reagents.Amount = Utility.Random(1, 4);
DropItem(reagents);
}
for (var i = Utility.Random(3); i > 0; i--)
{
var scrolls = Loot.RandomScroll(0, 47, SpellbookType.Regular);
scrolls.Amount = Utility.Random(1, 6);
DropItem(scrolls);
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomPotion());
}
for (var i = Utility.Random(3); i > 0; i--)
{
var gems = Loot.RandomGem();
gems.Amount = Utility.Random(1, 4);
DropItem(gems);
}
for (var i = Utility.Random(3); i > 0; i--)
{
DropItem(Loot.RandomWand());
}
if (Utility.RandomBool())
{
for (var i = Utility.Random(3); i > 0; i--)
{
var armor = Loot.RandomArmorOrShield();
armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(3);
armor.Durability = (ArmorDurabilityLevel)Utility.Random(3);
armor.Quality = ArmorQuality.Regular;
DropItem(armor);
}
}
}
}
}

View file

@ -1,95 +0,0 @@
using System;
using ModernUO.Serialization;
namespace Server.Items;
// ==============================================================
// LEVEL 4: 99% Trapped / 99% Locked (1% Lottery Ticket!)
// ==============================================================
[SerializationGenerator(0, false)]
public partial class TreasureBagLevel4 : BaseTreasureBag
{
[Constructible]
public TreasureBagLevel4()
{
Locked = Utility.RandomDouble() < 0.95; // 99% Locked (5% Unlocked)
RequiredSkill = 92;
LockLevel = RequiredSkill - Utility.Random(1, 10);
MaxLockLevel = RequiredSkill + Utility.Random(1, 10);
if (Utility.RandomDouble() < 0.99) // 99% Trapped
{
TrapType = TrapType.ExplosionTrap;
TrapPower = 4 * Utility.Random(10, 25);
}
// --- UNIFIED LOOT GENERATION ---
// Everyone gets this massive loot pool. The 1% just get to open it for free!
DropItem(new Gold(Utility.Random(500, 900)));
for (var i = Utility.Random(4) + 1; i > 0; i--)
{
var reagents = Loot.RandomReagent();
reagents.Amount = 12;
DropItem(reagents);
}
for (var i = Utility.Random(4) + 1; i > 0; i--)
{
var scroll = Loot.RandomScroll(0, 47, SpellbookType.Regular);
scroll.Amount = 16;
DropItem(scroll);
}
DropItem(new BlankScroll(Utility.Random(1, 4)));
for (var i = Utility.Random(4) + 1; i > 0; i--)
{
DropItem(Loot.RandomPotion());
}
for (var i = Utility.Random(4) + 1; i > 0; i--)
{
var gems = Loot.RandomGem();
gems.Amount = 12;
DropItem(gems);
}
for (var i = Utility.Random(4) + 1; i > 0; i--)
{
DropItem(Loot.RandomWand());
}
for (var i = Utility.Random(4) + 1; i > 0; i--)
{
var item = Loot.RandomArmorOrShieldOrWeapon();
if (item is BaseWeapon weapon)
{
weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(4);
weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(4);
weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(4);
weapon.Quality = WeaponQuality.Regular;
}
else if (item is BaseArmor armor)
{
armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(4);
armor.Durability = (ArmorDurabilityLevel)Utility.Random(4);
armor.Quality = ArmorQuality.Regular;
}
DropItem(item);
}
for (var i = Utility.Random(3) + 1; i > 0; i--)
{
DropItem(Loot.RandomClothing());
}
for (var i = Utility.Random(3) + 1; i > 0; i--)
{
DropItem(Loot.RandomJewelry());
}
}
}