fix: Require BOD combine items to be player-crafted

SmallBOD.EndCombine validates an item's type, material and exceptional
quality, but never checks that it was actually crafted by a player. Any
item matching the request can be turned in, including one bought from an
NPC vendor.

Where a vendor sells a type a BOD can request, this lets a player fill the
deed by buying the items rather than crafting them, and collect the reward
gold for the difference. Tailoring is the clearest case because
SmallTailorBOD.CreateRandomFor guarantees Material=None and
RequireExceptional=false below 70.1 skill, so the rolled deed asks for
plain cloth items that tailor vendors stock directly -- e.g. a qty-20
Bandana BOD filled from vendor stock, against a reward of several times
the purchase cost.

Adds a PlayerConstructed check alongside the existing material and quality
checks, following the pattern already used in Engines/Craft/Core/Resmelt.cs
for distinguishing crafted from store-bought items.

Note on the message: there is no dedicated cliloc for "this item must be
crafted", so 1045169 ("The item is not in the request.") is reused. Happy
to change it if a better one is known -- flagging it rather than inventing
a string.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kamron Batman 2026-08-12 20:03:17 -07:00
parent 1bc83339bb
commit 3759971c80
No known key found for this signature in database
GPG key ID: 7D81DF26D9A5D94A

View file

@ -136,8 +136,14 @@ public abstract partial class SmallBOD : BaseBOD
else
{
var material = GetMaterial(armor?.Resource ?? clothing?.Resource ?? CraftResource.None);
var playerConstructed = armor?.PlayerConstructed ?? clothing?.PlayerConstructed ??
weapon?.PlayerConstructed ?? false;
if (Material >= BulkMaterialType.DullCopper && Material <= BulkMaterialType.Valorite && material != Material)
if (!playerConstructed)
{
from.SendLocalizedMessage(1045169); // The item is not in the request.
}
else if (Material >= BulkMaterialType.DullCopper && Material <= BulkMaterialType.Valorite && material != Material)
{
from.SendLocalizedMessage(1045168); // The item is not made from the requested ore.
}