diff --git a/tools/scaffolding/BridgeVendorTestProbe.cs b/tools/scaffolding/BridgeVendorTestProbe.cs
new file mode 100644
index 0000000..08d3dd9
--- /dev/null
+++ b/tools/scaffolding/BridgeVendorTestProbe.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Reflection;
+
+using Server.Accounting;
+using Server.Items;
+using Server.Mobiles;
+
+namespace Server.Custom
+{
+ ///
+ /// Spawns a reachable, houseless player vendor next to the `tester` character (wttest) and
+ /// gives tester gold, so the PlayerVendorSale core patch can be exercised by a real in-game
+ /// purchase. The buyer must be a non-GM — IsOwner() treats any GameMaster+ as the owner of
+ /// every player vendor, so an Owner-level character can never buy.
+ ///
+ /// Owner is a seed_000 character, so buyer (wttest) and owner (seed_000) are different
+ /// accounts — a clean cheat-detection example.
+ ///
+ /// Test scaffolding. Never deployed. Spawns a mobile and hands out gold; run only on the
+ /// throwaway seeded world.
+ ///
+ public static class BridgeVendorTestProbe
+ {
+ private static readonly MethodInfo SetVendorItem = typeof(PlayerVendor).GetMethod(
+ "SetVendorItem",
+ BindingFlags.Instance | BindingFlags.NonPublic,
+ null,
+ new[] { typeof(Item), typeof(int), typeof(string) },
+ null);
+
+ public static void Initialize()
+ {
+ if (Config.Get("Bridge.VendorTestOnStart", false))
+ EventSink.ServerStarted += () => Timer.DelayCall(TimeSpan.FromSeconds(3.0), Run);
+ }
+
+ private static void Run()
+ {
+ try
+ {
+ var ownerAcct = Accounting.Accounts.GetAccount("seed_000") as Account;
+ var owner = ownerAcct == null ? null : ownerAcct[0];
+
+ var buyerAcct = Accounting.Accounts.GetAccount("wttest") as Account;
+ var buyer = buyerAcct == null ? null : buyerAcct[0] as PlayerMobile;
+
+ if (owner == null || buyer == null)
+ {
+ Console.WriteLine("[VendorTest] need seed_000 owner and wttest/tester; not found");
+ return;
+ }
+
+ // Remove any prior test vendor (e.g. one orphaned on the Internal map).
+ if (PlayerVendor.PlayerVendors != null)
+ {
+ var doomed = new System.Collections.Generic.List();
+ foreach (var v in PlayerVendor.PlayerVendors)
+ if (v != null && !v.Deleted && v.ShopName == "Bridge Test Shop")
+ doomed.Add(v);
+ foreach (var v in doomed)
+ v.Delete();
+ }
+
+ // A confirmed-walkable spot where tester was already standing this session, so the
+ // vendor is on solid ground and reachable. Then force tester's logout location right
+ // next to it, so tester logs in beside the vendor regardless of where it was.
+ var map = Map.Trammel;
+ var loc = new Point3D(3533, 2546, 20); // vendor
+ buyer.LogoutMap = map;
+ buyer.LogoutLocation = new Point3D(3532, 2546, 20); // tester appears here
+
+ var vendor = new PlayerVendor(owner, null)
+ {
+ Name = "test vendor",
+ ShopName = "Bridge Test Shop"
+ };
+ vendor.MoveToWorld(loc, map);
+
+ var blade = new Longsword();
+ vendor.Backpack.DropItem(blade);
+ if (SetVendorItem != null)
+ SetVendorItem.Invoke(vendor, new object[] { blade, 100, "a test blade" });
+
+ // Make sure tester can afford it.
+ if (buyer.Backpack != null)
+ buyer.Backpack.DropItem(new Gold(1000));
+
+ Console.WriteLine(
+ "[VendorTest] spawned '{0}' (owner {1}/seed_000) next to {2}/wttest at {3} on {4}; test blade = 100 gold; gave tester 1000 gold",
+ vendor.ShopName, owner.Name, buyer.Name, loc, map);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("[VendorTest] FAILED: " + ex);
+ }
+ }
+ }
+}