Commit graph

3403 commits

Author SHA1 Message Date
1efa69c9f4 #W# Added: Armor and shields now show ACTUAL AR rating. 2026-10-07 13:52:22 -04:00
e463db2955 #W# Fix: Newbie dungeon does accumulate mkp totalgold. 2026-10-07 12:53:32 -04:00
2a3551511e #W# DOTD: Added more rare rewards to the drop list. Set the default rare drop chance to 2% 2026-10-07 12:20:30 -04:00
4afeb5dd98 #W# DOTD: 50% more gold and 25% more MKPs. 2026-10-07 11:14:36 -04:00
cb5906025a #W# Feature: Added a Dungeon of the Day! [dotd command. Increased gold/skill gain/ and rare drops. 2026-10-07 10:52:08 -04:00
b6fa2cea69 #W# Region: Updated the dungeon regions abit. 2026-10-07 10:01:00 -04:00
68948ebdca #W# Spawns: Changed the min/max delay on monster spawners. 2026-10-07 09:31:50 -04:00
Kamron Batman
15a7ce55ce
fix: T2A tailoring make-last no longer reuses a stale cloth hue for leather (#2694)
## Summary
T2A tailoring Make Last failed after crafting a cloth item and then a leather item. `CraftContext.LastHue` was set only on the hued (cloth) path, so the next Make Last of a leather item took the hue-aware path and failed with "You don't have the resources". The leather path now resets `LastHue` to -1.

## Testing
- `dotnet build`: 0 warnings, 0 errors
- No automated test: driving `TailoringMenu` needs a NetState plus tiledata-backed resources, and CI has no tiledata. Not yet exercised in game.
2026-10-06 21:42:23 -07:00
b9cc7f8d9a #W# Fix: Shields now display str requirements. 2026-10-06 21:16:09 -04:00
1bffb190c4 #W# Removed: Removed the necromancer and chivalry npcs. 2026-10-06 20:54:07 -04:00
34b7945fc7 #W# Change: Changed to UOR expansion. Added Hover text for armor and weapons. 2026-10-06 20:51:27 -04:00
Jack
b98b0e2964
fix: digging up a treasure map chest no longer crashes when guardians spawn (#2692)
## Summary
Digging up a decoded treasure map of level 0, or of level 2 and above, throws inside `DigTimer.OnTick` once the chest surfaces. The exception escapes the timer, so the server goes down:

```
System.NullReferenceException: Object reference not set to an instance of an object.
   at Server.Items.TreasureMap.DigTimer.OnTick() in ...\Items\Maps\TreasureMap.cs:line 809
```

#2568 made `TreasureMapChest._guardians` lazily created: the constructor no longer initialises it, and migration nulls an empty list. #2569 updated the read in `CheckLocked` to match, but the dig timer still adds each spawned guardian directly:

```csharp
if (bc != null)
{
    m_Chest.Guardians.Add(bc); // null on a freshly dug chest
}
```

Level 1 maps survive only because they spawn no guardians. I confirmed the regression by running the dig test below at #2568's parent, where it passes, and at #2568, where it fails.

The dig timer now calls the generated `AddToGuardians`, which creates the list on first use.

## Testing
- `dotnet build`: 0 warnings, 0 errors.
- New `TreasureMapChestGuardianTests`:
  - `Dig_AddsSpawnedGuardiansToTheChest` (levels 0 and 2) drives the real `DigTimer` tick by tick until the chest surfaces. Before the fix both cases fail with the `NullReferenceException` above. It needs client map data, so it calls `TileDataRequirement.SkipIfMissing()` and skips on CI.
  - `AddToGuardians_OnNewChest_KeepsLevelZeroChestShut` needs no client data, so it runs on CI: the list starts null, the first guardian creates it, and a level 0 chest stays shut to players until that guardian is dead.
- Full `UOContent.Tests`: 1196 passed and 2 skipped with client data; 1105 passed and 93 skipped without.
2026-10-06 17:39:04 -07:00
fa33f8466d #W# Fix: Fixed a teleporter and a str typo for CowardlyBrigand 2026-10-06 20:15:03 -04:00
Jack
73a1aaf5e0
fix: MeteorSwarm resist halves that target's damage, not the shared pool (#2691)
## Summary
Pre-AOS, a Meteor Swarm target that resists should take half of its share of the damage. Instead the resist branch halves the **shared** `damage` variable:

```csharp
var toDeal = damage;

if (!Core.AOS && CheckResisted(m))
{
    damage *= 0.5;   // should be toDeal
```

`toDeal` has already been copied, so:
- the target that resisted takes **full** damage, and
- every target processed after it is halved, once per earlier resist, so a group where several resist ends up taking a fraction of the intended damage for reasons unrelated to their own resist.

`ChainLightning` already handles this correctly (`toDeal *= 0.5;`), and this change makes Meteor Swarm match it. The AOS path is unaffected, since resist checks only run pre-AOS.

The bug predates ModernUO (it was carried over from RunUO in the first alpha).

## Testing
- `dotnet build Projects/UOContent/UOContent.csproj`: 0 warnings, 0 errors.
- No unit test: the per-target damage sits inside `Target()`'s queue loop alongside a random resist roll, so testing it would mean refactoring the spell for a one-word fix. Happy to factor out a helper and add one if preferred.
2026-10-06 16:30:05 -07:00
615993dd3f #W# Spawns: Tweaked Bastion Cemetery spawns. 2026-10-06 15:46:41 -04:00
1f5ff9c95f #W# Fix: Fixed teleporter location. 2026-10-06 15:34:42 -04:00
6d9b2f6611 #W# Fix: Fixed wrong teleporters. 2026-10-06 15:15:34 -04:00
45ac268d7c #W# Dungeon: Added a New Player Dungeon with some weaker mobs for level 1. 2026-10-06 14:59:05 -04:00
11b620b0dc #W# Region: Added a new NewbieDungeonRegion. Accelerated skill gain upto 80.0 2026-10-05 19:45:14 -04:00
e337ca20bc #W# Tweak: New characters start with 20 thirst now. 2026-10-05 10:26:13 -04:00
be23031a32 #W# Added: Added a waterskin. Water only. Dclick will check surrounding area for water to refill or it will drink. 2026-10-05 10:12:55 -04:00
Sergi Rosell
261ea01ab4
fix: send crash reports and bound email retries (#2680)
Crash reports never reached SMTP: `SendCrashEmail` returned immediately when email was enabled and never called the sender. It now respects the enabled setting, sends the report, and waits up to 30 seconds before the crash handler returns and the process can exit.

The sender uses the `Message-ID` generated by `MimeMessage` and the sender address already added by each caller. This removes the duplicate `Message-ID` header and duplicate address within the `From` header. Gmail rejects duplicate `Message-ID` headers: https://support.google.com/a/answer/13567860.

Email retries use a bounded doubling schedule instead of squaring an integer delay, which could overflow and throw through an `async void` method. The sender returns `Task`, uses `ConfigureAwait(false)` throughout, and logs failures. With the default five attempts and three-second initial delay, waits are 3, 6, 12, and 24 seconds. Each wait is capped at one hour, and there is no wait after the last attempt.

Validation:

- Full Release test suite on the branch updated with `main`: 2,103 passed, 2 intentionally skipped.
- Eight email test cases cover disabled-email early returns, retry timing, low attempt counts, and overflow-prone delays.
- SMTP delivery and the crash-time shutdown path are not covered by an integration test.
2026-10-04 18:41:27 -07:00
Sergi Rosell
6102cdabd7
fix: players jailed across a restart can be jailed again after release (#2690)
Loading the jail records added every player still serving a sentence to
CurrentlyBeingJailed, which only guards the jail sequence and is cleared
when it ends. Nothing removed them on release, so JailPlayer silently
returned for them until the next restart.
2026-10-04 18:21:50 -07:00
Sergi Rosell
b7d93f5126
fix: fishing catches by expansion, SOS facets and the big fish mark (#2688)
The fishing mutate table offers every special catch in every era, so a pre-T2A shard fishes up boots, magic fish, treasure maps and bottles (added in the March 1999 fishing update), and a T2A shard gets the special fishing net and big fish, which no T2A publish or guide lists.

Each entry now carries the expansion that added it; the chances are unchanged. The nets in SOS chests and on krakens need UO:R as well, and before SE ancient SOS roll 1 in 40 and their chests aren't hued white, since Publish 28 changed both.

Two fixes from the same notes come with it. An SOS now only works in the facet it was found in, so kraken and leviathan bottles are made at death with the creature's facet. Big fish, their trophy deed and their trophy show the fisherman's mark and weight only from SE.

## Why each change

### The rule

- `Core.T2A`, `Core.UOR`, `Core.SE`… mean "the shard is this expansion **or newer**".
- An expansion includes every publish that came out while it was the newest one. Publish 27 (September 2004) came out before Samurai Empire (November 2004), so it belongs to AOS.
- An item can't drop on a shard older than the expansion that added it.
- When the sources only narrow it down to a window that spans two expansions, the item takes the older one, so no shard loses something it may really have had.

### When each fishing item arrived

| Expansion | Released | What it added to fishing | Sources |
|---|---|---|---|
| T2A | Oct 1, 1998 | Boots, magic fish, treasure maps, bottles (update of March 17, 1999) | [1] |
| UO:R | May 4, 2000 | Special fishing net (first listed in August 2000) | [2], [6], [7] |
| UO:R or Third Dawn | | Big fish (first listed between November 2000 and March 2001) | [3], [8], [9] |
| AOS | Feb 11, 2003 | Ancient SOS at 1 in 40, fabled fishing net (Publish 27, September 14, 2004) | [4] |
| SE | Nov 2, 2004 | Ancient SOS at 1 in 25, white ancient chests, the fisherman's mark on big fish (Publish 28, January 12, 2005) | [5] |

Release dates: [13].

### `Fishing.cs`

**`MutateEntry` gets an `Expansion` field and constructor argument.**
Each row has to know which expansion added it. `MutateEntry` is private to `Fishing`, so no other code is affected.

**`MutateType` skips rows newer than the shard:**

```csharp
if (Core.Expansion < entry.m_Expansion)
{
    continue;
}
```

A skipped row behaves as if it weren't in the table. Every other row rolls exactly as before.

**The rows:**

| Row | Expansion | Why |
|---|---|---|
| Boots, shoes, sandals, thigh boots | T2A | The March 17, 1999 update is the first time fishing gives anything but fish: "you now have a chance of pulling up … One of any of several types of boots". [1] |
| Magic fish (prized, wondrous, truly rare, peculiar) | T2A | Same update: "Magical fish, which can boost stamina, strength, intelligence, or dexterity". [1] |
| Treasure map | T2A | Same update: "Treasure maps". [1] |
| Message in a bottle | T2A | Same update: "Messages in bottles". [1] |
| Special fishing net | UO:R | Missing from the 1999 list [1] and from the March 2000 fishing changes, which only mention treasure maps and SOS bottles [2]. Stratics' fishing guide doesn't have it from July 1999 to July 8, 2000 [6] and has it on August 10, 2000 [7], after UO:R came out. |
| Big fish | UO:R | Stratics' fishing guide doesn't have it from July 1999 [6] to November 7, 2000 [8] and has it on May 24, 2001 [9]. Publish 11 (March 14, 2001) already lets taxidermy kits use it [3]. So it is certainly not T2A. It came at the end of UO:R or with Third Dawn (March 7, 2001); the sources can't tell which, so it takes UO:R, the older one. |
| Nothing (the empty row) | None | Exists in every expansion; unchanged. |

**SOS chest, white hue: `if (sos.IsAncient && Core.SE)`**
Publish 28: "Hued level 4 fishing chests white." [5] It came out after SE, so before SE the ancient chest keeps its normal colour.

**SOS chest, net: `if (Core.UOR) { chest.DropItem(...); }`**
You can fish up an SOS chest from T2A on, because bottles are T2A [1]. The net inside it is UO:R (see the table), so before UO:R the chest comes without a net. The fabled net only goes in ancient chests, and those already need AOS [4].

**SOS: `from.Map == sos.TargetMap`, in `CheckResources` and `Construct`**
Both accepted an SOS whenever the fisher was in Felucca or Trammel, without comparing the SOS's `TargetMap`, so a Trammel SOS paid out in Felucca at the same spot. Publish 5: "SOS bottles and treasure maps will only work in the land they are found in (for instance, a map found in Felucca will only work in Felucca)." [14] Treasure maps already check their facet.

### `MessageInABottle.cs`

**`GetRandomLevel`: `Utility.Random(Core.SE ? 25 : 40) < 1`**
Publish 27 added ancient SOS at "a 1 in 40 chance" [4]. Publish 28 "Changed Ancient SoS spawn chance from 1 in 40 to 1 in 25" [5]. So AOS rolls 1 in 40, SE and newer 1 in 25. The `Core.AOS` check was already there.

### `Kraken.cs`

**Bottle, now made in `OnBeforeDeath`: `if (Core.T2A && Utility.RandomDouble() < .05)`**
Bottles don't exist before T2A [1], so a kraken can't carry one there. The 5% is unchanged; no official source gives a number. The kraken is in Stratics' 1999 creature list [10]; its kraken page says "Loot: Unknown" in January 2000 [11] and "Loot: Messages in a Bottle, Treasure Maps, 300 - 600 gold" in October 2000 [12].

The constructor packed the bottle before the kraken had a map, so it always pointed to Trammel; with the SOS check above, a kraken killed in Felucca would drop an SOS that only works in Trammel. It is now made at death with the kraken's facet, as `BaseCreature.OnBeforeDeath` does for treasure maps; the net already does the same for the kraken it brings up.

**Net: `if (Core.UOR) { PackItem(new SpecialFishingNet()); // Confirm? }`**
Nets are UO:R [6], [7]. The `// Confirm?` stays: in 2000 Stratics says the net was "loot on Sea Serpents" [7], [12], not on krakens. Which creature drops the net is out of scope; this PR only fixes the expansion.

### `Leviathan.cs`

**Bottle, now made in `OnBeforeDeath`**
Same as the kraken: it was packed in the constructor and pointed to Trammel. It is now made at death with the leviathan's facet, and still drops every time.

### `BigFish.cs` and `TaxidermyKit.cs`

**Mark and weight: `if (Core.SE && Weight >= 20)`, and the same in the trophy and its deed**
Publish 28: "Added variable weight and fisherman's mark on big fish, big fish trophy deed, and big fish trophy. Any big fish caught that is below 20 stones will not display weight or fisherman's mark." [5] It came out after SE, so before SE none of the three shows them.

### What this PR doesn't change

No chance, skill threshold or row order changes. The open questions (which creature drops the net, the exact expansion of big fish, its weight before Publish 28, the rates) are in #2687.

## References

1. Origin Update Center, update of March 17, 1999: the fishing overhaul that adds boots, magic fish, treasure maps and bottles. https://web.archive.org/web/19990417083713/http://update.owo.com/latest.html
2. Publish 4, March 8, 2000: "Every time you successfully fish up a treasure map or SOS bottle a sea serpent will surface and attack." https://uo.com/wiki/ultima-online-wiki/technical/previous-publishes/2000-2/2000-publish-04-8th-march/ (copy from the time: https://web.archive.org/web/20000408162342/http://update.uo.com/design_180.html)
3. Publish 11, March 14, 2001: taxidermy kits accept "Big Fish". https://uo.com/wiki/ultima-online-wiki/technical/previous-publishes/2001-2/2001-publish-11-14th-march/ (copy from the time: https://web.archive.org/web/20010331072129/http://update.uo.com/design_321.html)
4. Publish 27, September 14, 2004: "There is a 1 in 40 chance that any message in a bottle becomes 'an ancient SOS'", "Added fabled fishing nets and ancient sos treasure". https://uo.com/wiki/ultima-online-wiki/technical/previous-publishes/2004-2/publish-27/
5. Publish 28, January 12, 2005: "Hued level 4 fishing chests white", "Changed Ancient SoS spawn chance from 1 in 40 to 1 in 25". https://uo.com/wiki/ultima-online-wiki/technical/previous-publishes/2005-2/publish-28-12th-january/
6. Stratics fishing guide without the net or big fish, the same text from July 24, 1999 to July 8, 2000: last modified July 24, 1999, https://web.archive.org/web/19991009203653/http://uo.stratics.com:80/fishing.htm ; last modified July 8, 2000, https://web.archive.org/web/20000711071050/http://uo.stratics.com:80/fishing.shtml
7. Stratics fishing guide, last modified August 10, 2000: lists the special fishing net, "found as loot on sea serpents". https://web.archive.org/web/20000831173915/http://uo.stratics.com:80/fishing.shtml
8. Stratics fishing guide, last modified November 7, 2000: still no big fish. https://web.archive.org/web/20001209013100/http://uo.stratics.com:80/fishing.shtml
9. Stratics fishing guide, last modified May 24, 2001: lists big fish. https://web.archive.org/web/20010608153326/http://uo.stratics.com:80/content/skills/fishing.shtml
10. Stratics Hunter's Guide menu, last modified July 4, 1999: the kraken is in the creature list. https://web.archive.org/web/19991013090543/http://uo.stratics.com:80/hunters/huntmenu.htm
11. Stratics kraken page, last modified January 1, 2000: "Loot: Unknown". https://web.archive.org/web/20000119061647/http://uo.stratics.com:80/hunters/kraken.html
12. Stratics kraken page, last modified October 15, 2000: "Loot: Messages in a Bottle, Treasure Maps, 300 - 600 gold"; the net "can be found as loot on Sea Serpents". https://web.archive.org/web/20001017190252/http://uo.stratics.com:80/hunters/kraken.shtml
13. Expansion release dates: https://en.wikipedia.org/wiki/Ultima_Online#Expansions_and_follow-up_releases
14. Publish 5, April 27, 2000: "SOS bottles and treasure maps will only work in the land they are found in". https://uo.com/wiki/ultima-online-wiki/technical/previous-publishes/2000-2/2000-publish-05-27th-april/ (copy from the time: https://web.archive.org/web/20000510032101/http://update.uo.com/design_196.html)
2026-10-04 18:17:05 -07:00
Sergi Rosell
ab89cd80f5
fix: release a connection's gumps on disconnect (#2689)
`GumpSystem` clears a connection's gumps on `EventSink.Disconnected`, but `Mobile.NetState` raises it after the state is already null, so nothing is ever removed: every connection that touched a gump stays in `_gumps` until restart, with any gumps still open when it closed.

It now listens to `BeforeDisconnected`, while `m.NetState` still returns the connection. That event also fires on login, where there is no previous state and the handler does nothing.
2026-10-04 17:53:41 -07:00
Sergi Rosell
d26ae63e94
fix: duel teams start on their own arena points, in formation (#2686)
* fix: duel teams start on their own arena points, in formation

MoveInside clamped the team index with Math.Min instead of Math.Max, so
every team started on the west edge point. The formation rotation also
reused the already-rotated X when computing Y, stacking players on the
north and south edges, and the SW/NE corners swapped axes, which leaves
the corner formation pointing out of the arena.

* refactor: one start point index clamp for GetBaseStartPoint and MoveInside

The clamp was written twice, and only one copy was correct.

* refactor: leave the placement loop as it was

Only the rotation lines in the loop belong to the fix.
2026-10-04 17:48:10 -07:00
1be86c0a40 #W# Added: Hunger and Thirst now matter. Taking damage now gives you exhaustion points that will lower your hunger and thirst faster. 2026-10-04 18:26:52 -04:00
7ca5cd3a4e #W# Added: Added a [mystats command to view the stuff i'm tracking. 2026-10-04 12:35:56 -04:00
d7f998cf6b #W# Added: Healing bufficon. 2026-10-03 20:29:18 -04:00
65d434c44a #W# Added: Now tracking player deaths, mobs kill (need to drop gold) and total gold, doesn't have to be looted. 2026-10-03 20:07:08 -04:00
ce9983b081 #W# Added: I am now tracking monster kills. Points are based on mob fame. Also added a nice [StatusBar command. 2026-10-03 18:32:43 -04:00
86b15bbc8e #W# Region: Fixes Shames entrance region. 2026-10-03 13:02:13 -04:00
c34a5f18a5 #W# Typo: Fixed a Typo. 2026-10-03 12:57:48 -04:00
d9e52d5d0e #W# Region: Fixes Shames entrance region. 2026-10-03 12:56:37 -04:00
b787df9164 #W# Bug Fix: Removed Exile Hunter Stuff. Seems buggy. 2026-10-03 12:50:44 -04:00
9503ad1513 #W# Weather: Setup snowy weather for the winter islands. 2026-10-03 10:53:01 -04:00
db20bb768e #W# Typo: Fixed typo in region.json 2026-10-03 09:40:21 -04:00
7e67f8f93e #W# Added: MineClutter added to the ToAdd folder. 2026-10-03 09:34:51 -04:00
acbcfe729b #W# Spawns: Lots of dungeon spawn and decration work. 2026-10-02 21:21:55 -04:00
314a2384d2 #W# Added: Settings.cs has some custimizable settings exposed for easy tweaking. 2026-10-02 13:59:36 -04:00
c1c3c1b30d #W# Spawns: Covetous dungeon is spawned and doors are done. 2026-10-02 12:30:53 -04:00
292cd625c5 #W# Added: Added an Overworld dungeon region. Tweaked overworld animal spawn. 2026-10-01 20:37:16 -04:00
6213604bb1 #W# Skill: The heal skill is now activatable. It heal poison/bleed 100% has a 15 second timer. 2026-10-01 18:53:52 -04:00
e92d8ed078 #W# Change: Decided AOS would be a good expansion to use over UOR. 2026-10-01 18:32:58 -04:00
10d1368fb3 #W# Work: Working on innate abilities. 2026-10-01 17:20:22 -04:00
a628d30ed6 #W# Work: Working on innate abilities. 2026-10-01 13:45:10 -04:00
c22afc8ad6 #W# Tweak: Tweaked FarmSpawner times. 2026-10-01 11:36:01 -04:00
eb35515ad8 #W# Update: Updated BuildWorld gump. 2026-10-01 11:33:26 -04:00
e2f88e01e0 #W# Fix: Fixed wrong teleporters. 2026-10-01 10:46:45 -04:00
029b4c2bc3 #W# Gumps: Tweaked the admin gump to use the new buildworld gump. Also added [buildworld command. 2026-10-01 10:26:01 -04:00