diff --git a/Distribution/Data/treasure.cfg b/Distribution/Data/treasure.cfg
index 7ca58c917..b31a4d12a 100644
--- a/Distribution/Data/treasure.cfg
+++ b/Distribution/Data/treasure.cfg
@@ -1,193 +1 @@
-2643 851
-2672 392
-3404 238
-3369 637
-2740 435
-2770 345
-2781 289
-2836 233
-3014 250
-3082 202
-3246 245
-3375 458
-1314 317
-1470 229
-1504 366
-2340 645
-2350 688
-2395 723
-2433 767
-1319 889
-1414 771
-1529 753
-1555 806
-1511 967
-1510 1071
-1562 1058
-961 506
-1162 189
-2337 1159
-2392 1154
-2517 1066
-2458 1042
-1658 2030
-2062 1962
-2089 1987
-2097 1975
-2066 1979
-2058 1992
-2071 2007
-2093 2006
-2187 1991
-1689 1993
-1709 1964
-1726 1998
-1731 2016
-1743 2028
-1754 2020
-2033 1942
-2054 1962
-581 1455
-358 1337
-208 1444
-199 1461
-348 1565
-620 1706
-1027 1180
-1037 1975
-1042 1960
-1042 1903
-1034 1877
-1018 1859
-980 1849
-962 1858
-977 1879
-968 1884
-969 1893
-974 1992
-989 1992
-1024 1990
-2648 2167
-2956 2200
-2968 2170
-2957 2150
-2951 2177
-2629 2221
-2642 2289
-2682 2290
-2727 2309
-2782 2293
-2804 2255
-2850 2252
-2932 2240
-3425 2723
-3476 2761
-3594 2825
-4419 3117
-4471 3188
-4507 3227
-4496 3241
-4642 3369
-4694 3485
-4448 3130
-4453 3148
-4500 3108
-4513 3103
-4424 3152
-4466 3209
-4477 3230
-4477 3282
-2797 3452
-2803 3488
-2793 3519
-2831 3511
-2989 3606
-3035 3603
-1427 2405
-1466 2181
-1519 2214
-1523 2150
-1541 2115
-1534 2189
-1546 2221
-1595 2193
-1619 2236
-1654 2268
-1655 2304
-1433 2381
-1724 2288
-1703 2318
-1772 2321
-1758 2333
-1765 2430
-1647 2641
-1562 2705
-1670 2808
-1471 2340
-1562 2312
-1450 2301
-1437 2294
-1478 2273
-1464 2245
-1439 2217
-1383 2840
-1388 2984
-1415 3059
-1602 3012
-1664 3062
-2062 2144
-2178 2151
-2104 2123
-2098 2101
-2123 2120
-2130 2108
-2129 2132
-2153 2120
-2162 2148
-2186 2144
-492 2027
-477 2044
-451 2053
-468 2087
-465 2100
-958 2504
-1025 2702
-1290 2735
-2013 3269
-2149 3362
-2097 3384
-2039 3427
-2516 3999
-2453 3942
-2528 3982
-2513 3962
-2512 3918
-2513 3901
-2480 3908
-2421 3902
-2415 3920
-2422 3928
-2370 3428
-2341 3482
-2360 3507
-2387 3505
-2152 3950
-2157 3924
-2140 3940
-2143 3986
-2154 3983
-2162 3988
-2467 3581
-2527 3585
-2482 3624
-2535 3608
-1090 3110
-1094 3131
-1073 3133
-1076 3156
-1068 3182
-1096 3178
-1129 3403
-1135 3445
-1162 3469
-1128 3500
\ No newline at end of file
+1889 2164
diff --git a/Projects/UOContent/Gumps/TreasureLocationGump.cs b/Projects/UOContent/Gumps/TreasureLocationGump.cs
new file mode 100644
index 000000000..dcd8b5f60
--- /dev/null
+++ b/Projects/UOContent/Gumps/TreasureLocationGump.cs
@@ -0,0 +1,58 @@
+using System;
+using Server;
+using Server.Gumps;
+using Server.Misc; // Needed for NameList.RandomName
+
+namespace Server.Gumps
+{
+ public class TreasureLocationGump : Gump
+ {
+ public TreasureLocationGump(int level, Point2D loc, Map map) : base(100, 100)
+ {
+ Closable = true;
+ Disposable = true;
+ Resizable = false;
+
+ AddPage(0);
+
+ AddBackground(0, 0, 350, 260, 9270);
+ AddAlphaRegion(10, 10, 330, 240);
+
+ // Header
+ AddHtml(0, 15, 350, 20, $"
Level {level} Treasure Map", false, false);
+
+ // Fetch the narrative lore
+ string flavorText = GetFlavorText(level, loc);
+
+ // Story Text Area
+ AddHtml(25, 50, 300, 120, $"{flavorText}", false, false);
+
+ // Footer / Clean Coordinate Readout
+ AddHtml(0, 180, 350, 20, $"Facet: {map.Name}", false, false);
+ AddHtml(0, 205, 350, 20, $"Target Coordinates: {loc.X}, {loc.Y}", false, false);
+ }
+
+ private string GetFlavorText(int level, Point2D loc)
+ {
+ // We use standard "male" or "female" generic name lists to ensure it never crashes looking for a custom list
+ string randomMage = NameList.RandomName(Utility.RandomBool() ? "male" : "female");
+
+ return level switch
+ {
+ 1 => $"In my haste I had to dump my treasure at {loc.X}, {loc.Y}. I hope to return for it soon before the scavengers find it.",
+
+ 2 => $"The local guard patrol got too close. I buried the stash at {loc.X}, {loc.Y} and marked the spot. They'll never find it.",
+
+ 3 => $"We lost half the crew to the beasts in these woods. I hid the remaining loot at {loc.X}, {loc.Y} so we can travel light.",
+
+ 4 => $"The dead walk this land. I dared not carry the gold any further. I sealed it away at {loc.X}, {loc.Y}, but I fear they watch it now.",
+
+ 5 => $"The Evil Mage {randomMage} found me! I stashed the treasure at {loc.X}, {loc.Y}. Be warned though, the treasure has a curse on it that I haven't figured out how to break yet.",
+
+ 6 => $"A creature of ancient, unimaginable power claimed this territory. I buried the chest deep at {loc.X}, {loc.Y}. If you are reading this, I am already dead.",
+
+ _ => $"A modest stash of goods hidden away at {loc.X}, {loc.Y}."
+ };
+ }
+ }
+}
diff --git a/Projects/UOContent/Items/Maps/TreasureMap.cs b/Projects/UOContent/Items/Maps/TreasureMap.cs
index fd2a9d75d..eeddf6b93 100644
--- a/Projects/UOContent/Items/Maps/TreasureMap.cs
+++ b/Projects/UOContent/Items/Maps/TreasureMap.cs
@@ -8,6 +8,7 @@ using Server.Engines.Harvest;
using Server.Mobiles;
using Server.Network;
using Server.Targeting;
+using Server.Gumps;
namespace Server.Items;
@@ -63,7 +64,7 @@ public partial class TreasureMap : MapItem
public TreasureMap(int level, Map map)
{
_level = level;
- _chestMap = map;
+ _chestMap = Map.Trammel; //map;
_chestLocation = level == 0 ? GetRandomHavenLocation() : GetRandomLocation();
@@ -377,7 +378,7 @@ public partial class TreasureMap : MapItem
3 => 51.0,
4 => 61.0,
5 => 70.0,
- 6 => 70.0,
+ 6 => 100.1,
_ => 0.0
};
}
@@ -452,7 +453,11 @@ public partial class TreasureMap : MapItem
}
from.PlaySound(0x249);
- base.DisplayTo(from);
+ if (from is PlayerMobile pm)
+ {
+ pm.CloseGump();
+ pm.SendGump(new TreasureLocationGump(_level, ChestLocation, _chestMap));
+ }
}
public override void GetContextMenuEntries(Mobile from, ref PooledRefList list)
diff --git a/Projects/UOContent/Items/Skill Items/Thief/LockPick.cs b/Projects/UOContent/Items/Skill Items/Thief/LockPick.cs
index a839a0858..267d5af18 100644
--- a/Projects/UOContent/Items/Skill Items/Thief/LockPick.cs
+++ b/Projects/UOContent/Items/Skill Items/Thief/LockPick.cs
@@ -118,14 +118,39 @@ public partial class Lockpick : Item
return;
}
- if (_from.Skills.Lockpicking.Value < _item.RequiredSkill)
+ // 1. Fetch default lock values (used for doors, house locks, standard crates)
+ double minSkill = _item.LockLevel;
+ double maxSkill = _item.MaxLockLevel;
+ double reqSkill = _item.RequiredSkill;
+
+ // 2. Intercept TreasureMapChest to apply our custom tier math
+ if (_item is TreasureMapChest tmChest)
{
- // The LockLevel is higher thant the LockPicking of the player
+ minSkill = tmChest.Level switch
+ {
+ 1 => 15.0,
+ 2 => 35.0,
+ 3 => 55.0,
+ 4 => 75.0,
+ 5 => 90.0,
+ 6 => 100.1, // Requires Lockpicking Power Scroll
+ _ => tmChest.Level * 16.7
+ };
+
+ reqSkill = minSkill; // Sets the floor so they can't even attempt it if too low
+ maxSkill = minSkill + 25.0;
+ }
+
+ // 3. Apply the dynamic required skill
+ if (_from.Skills.Lockpicking.Value < reqSkill)
+ {
+ // The LockLevel is higher than the LockPicking of the player
item.SendLocalizedMessageTo(_from, 502072); // You don't see how that lock can be manipulated.
return;
}
- if (_from.CheckTargetSkill(SkillName.Lockpicking, _item, _item.LockLevel, _item.MaxLockLevel))
+ // 4. Roll the dice using the dynamic min/max variables
+ if (_from.CheckTargetSkill(SkillName.Lockpicking, _item, minSkill, maxSkill))
{
// Success! Pick the lock!
item.SendLocalizedMessageTo(_from, 502076); // The lock quickly yields to your skill.
diff --git a/Projects/UOContent/Skills/ItemIdentification.cs b/Projects/UOContent/Skills/ItemIdentification.cs
index 19ddf585d..e3a160bda 100644
--- a/Projects/UOContent/Skills/ItemIdentification.cs
+++ b/Projects/UOContent/Skills/ItemIdentification.cs
@@ -21,7 +21,7 @@ public static class ItemIdentification
from.SendLocalizedMessage(500343); // What do you wish to appraise and identify?
from.Target = new InternalTarget();
- return TimeSpan.FromSeconds(1.0);
+ return TimeSpan.FromSeconds(3.0);
}
[PlayerVendorTarget]
diff --git a/Projects/UOContent/Skills/RemoveTrap.cs b/Projects/UOContent/Skills/RemoveTrap.cs
index 3a80f9e40..912d09804 100644
--- a/Projects/UOContent/Skills/RemoveTrap.cs
+++ b/Projects/UOContent/Skills/RemoveTrap.cs
@@ -28,7 +28,7 @@ namespace Server.SkillHandlers
m.SendLocalizedMessage(502368); // Which trap will you attempt to disarm?
}
- return TimeSpan.FromSeconds(10.0); // 10 second delay before being able to re-use a skill
+ return TimeSpan.FromSeconds(5.0); // 5 second delay before being able to re-use a skill
}
private class InternalTarget : Target
@@ -58,7 +58,19 @@ namespace Server.SkillHandlers
from.PlaySound(0x241);
- if (from.CheckTargetSkill(SkillName.RemoveTrap, targ, targ.TrapPower, targ.TrapPower + 30))
+ double minSkill = targ.TrapLevel switch
+ {
+ 1 => 15.0,
+ 2 => 35.0,
+ 3 => 55.0,
+ 4 => 75.0, // Level 4: 75.0 Min
+ 5 => 90.0, // Level 5: 90.0 Min (GM has a 40% chance)
+ 6 => 100.1, // Level 6: 100.1 Min (Base GM has 0% chance. Requires Power Scroll)
+ _ => targ.TrapLevel * 16.7 // Fallback for custom Level 7+ maps
+ };
+ double maxSkill = minSkill + 25.0;
+
+ if (from.CheckTargetSkill(SkillName.RemoveTrap, targ, minSkill, maxSkill))
{
targ.TrapPower = 0;
targ.TrapLevel = 0;
diff --git a/Projects/UOContent/Spells/Third/Telekinesis.cs b/Projects/UOContent/Spells/Third/Telekinesis.cs
index 47051f92e..247500096 100644
--- a/Projects/UOContent/Spells/Third/Telekinesis.cs
+++ b/Projects/UOContent/Spells/Third/Telekinesis.cs
@@ -21,6 +21,12 @@ namespace Server.Spells.Third
public void Target(Item item)
{
+ if (item is TreasureMapChest)
+ {
+ Caster.SendLocalizedMessage(501857); // This spell won't work on that!
+ return;
+ }
+
var t = item as ITelekinesisable;
if (!(t != null || item is Container))
{