mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-11 11:33:52 +00:00
feat(editor): add WTRD (Trade Window Rules) — 115th open format
Novel replacement for the implicit player-to-player trade policy rules vanilla WoW hardcoded across the trade-window message handlers (CMSG_INITIATE_TRADE, CMSG_SET_TRADE_ITEM, CMSG_SET_TRADE_GOLD), the soulbound-item check, the cross-faction-trade rejection, and the GM-trade audit hooks. Each entry is one trade-policy rule the trade-window state machine consults at every state transition. Seven ruleKind values (Allowed / Forbidden / SoulboundException / CrossFactionAllowed / LevelGated / GoldEscrowMax / AuditLogged) and five targetingFilter values (AnyPlayer / SameRealmOnly / SameFactionOnly / SameAccountOnly / GMOnly) cover the full trade-policy surface. Priority field resolves rule conflicts — higher priority wins (Allowed at 100 overrides Forbidden at 10). Three preset emitters cover real-world deployment patterns: makeStandard (4 baseline rules — Soulbound Forbidden globally, Quest items Forbidden, 2hr Soul- boundException for raid trade-back, SameFactionOnly), makeServerAdmin (3 server-custom overrides — GM-only escrow at priority 100, AccountBound own-character transfer, CrossFactionAllowed at level 80 for RP servers), makeRMTPrevent (4 anti-RMT rules — 10g cap for low-level trades, 500g cap for accounts < 30 days, audit log for trades > 1000g, 24hr first-trade delay). Validator's most novel check is the GoldEscrowMax / goldEscrowMaxCopper consistency rule: a GoldEscrowMax- kind rule MUST specify a non-zero gold cap (zero would mean unlimited which contradicts the rule's purpose). Also warns on GMOnly targeting with priority < 50 (GM- mediated rules typically need high priority to override player-initiated rules) and levelRequirement > 80 (exceeds current cap, rule never applies). Format count 114 -> 115. CLI flag count 1227 -> 1232.
This commit is contained in:
parent
65c51a272f
commit
05bb96d23b
10 changed files with 744 additions and 0 deletions
144
include/pipeline/wowee_trade_rules.hpp
Normal file
144
include/pipeline/wowee_trade_rules.hpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace wowee {
|
||||
namespace pipeline {
|
||||
|
||||
// Wowee Open Trade Window Rules catalog (.wtrd) —
|
||||
// novel replacement for the implicit player-to-player
|
||||
// trade policy rules vanilla WoW hardcoded across the
|
||||
// trade-window message handlers (CMSG_INITIATE_TRADE,
|
||||
// CMSG_SET_TRADE_ITEM, CMSG_SET_TRADE_GOLD), the
|
||||
// soulbound-item check, the cross-faction-trade
|
||||
// rejection, and the GM-trade audit hooks. Each entry
|
||||
// is one trade policy rule the trade-window state
|
||||
// machine consults at every state transition.
|
||||
//
|
||||
// Cross-references with previously-added formats:
|
||||
// WIT: itemCategoryFilter uses the WIT item-class
|
||||
// + subclass bit conventions (Weapon=2,
|
||||
// Armor=4, Container=1, etc.).
|
||||
// WCHC: targetingFilter uses the WCHC faction-bit
|
||||
// convention for SameFactionOnly.
|
||||
//
|
||||
// Binary layout (little-endian):
|
||||
// magic[4] = "WTRD"
|
||||
// version (uint32) = current 1
|
||||
// nameLen + name (catalog label)
|
||||
// entryCount (uint32)
|
||||
// entries (each):
|
||||
// ruleId (uint32)
|
||||
// nameLen + name
|
||||
// descLen + description
|
||||
// ruleKind (uint8) — Allowed / Forbidden /
|
||||
// SoulboundException /
|
||||
// CrossFactionAllowed /
|
||||
// LevelGated /
|
||||
// GoldEscrowMax /
|
||||
// AuditLogged
|
||||
// targetingFilter (uint8) — AnyPlayer /
|
||||
// SameRealmOnly /
|
||||
// SameFactionOnly /
|
||||
// SameAccountOnly /
|
||||
// GMOnly
|
||||
// levelRequirement (uint8) — 0 = no level gate
|
||||
// priority (uint8) — higher overrides
|
||||
// lower in conflict
|
||||
// itemCategoryFilter (uint32) — bitmask of
|
||||
// WIT item classes
|
||||
// goldEscrowMaxCopper (uint64) — max gold side for
|
||||
// this rule (0 =
|
||||
// unlimited)
|
||||
// iconColorRGBA (uint32)
|
||||
struct WoweeTradeRules {
|
||||
enum RuleKind : uint8_t {
|
||||
Allowed = 0, // explicitly allow
|
||||
// (highest-priority
|
||||
// override)
|
||||
Forbidden = 1, // block trade if
|
||||
// category bits
|
||||
// match
|
||||
SoulboundException = 2, // 2hr trade-back
|
||||
// window post-loot
|
||||
CrossFactionAllowed = 3, // server-custom
|
||||
// override of base
|
||||
// same-faction rule
|
||||
LevelGated = 4, // require both
|
||||
// players >=
|
||||
// levelRequirement
|
||||
GoldEscrowMax = 5, // cap gold side at
|
||||
// goldEscrowMaxCopper
|
||||
AuditLogged = 6, // log every trade
|
||||
// matching this rule
|
||||
};
|
||||
|
||||
enum TargetingFilter : uint8_t {
|
||||
AnyPlayer = 0,
|
||||
SameRealmOnly = 1,
|
||||
SameFactionOnly = 2,
|
||||
SameAccountOnly = 3, // own-character transfer
|
||||
GMOnly = 4, // requires GM flag on
|
||||
// initiator
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
uint32_t ruleId = 0;
|
||||
std::string name;
|
||||
std::string description;
|
||||
uint8_t ruleKind = Forbidden;
|
||||
uint8_t targetingFilter = AnyPlayer;
|
||||
uint8_t levelRequirement = 0;
|
||||
uint8_t priority = 1;
|
||||
uint32_t itemCategoryFilter = 0;
|
||||
uint64_t goldEscrowMaxCopper = 0;
|
||||
uint32_t iconColorRGBA = 0xFFFFFFFFu;
|
||||
};
|
||||
|
||||
std::string name;
|
||||
std::vector<Entry> entries;
|
||||
|
||||
bool isValid() const { return !entries.empty(); }
|
||||
|
||||
const Entry* findById(uint32_t ruleId) const;
|
||||
|
||||
// Returns all rules of one kind (e.g. all Forbidden
|
||||
// rules to enumerate the explicit blocks). Used by
|
||||
// the trade-window state machine to dispatch checks
|
||||
// by kind.
|
||||
std::vector<const Entry*> findByKind(uint8_t ruleKind) const;
|
||||
};
|
||||
|
||||
class WoweeTradeRulesLoader {
|
||||
public:
|
||||
static bool save(const WoweeTradeRules& cat,
|
||||
const std::string& basePath);
|
||||
static WoweeTradeRules load(const std::string& basePath);
|
||||
static bool exists(const std::string& basePath);
|
||||
|
||||
// Preset emitters used by --gen-trd* variants.
|
||||
//
|
||||
// makeStandard — 4 standard trade rules
|
||||
// (Soulbound Forbidden globally,
|
||||
// Quest items Forbidden, 2hr
|
||||
// SoulboundException for raid
|
||||
// drops, SameFactionOnly default).
|
||||
// makeServerAdmin — 3 server-admin rules (GM-only
|
||||
// escrow trade, AccountBound
|
||||
// own-character transfer, Cross-
|
||||
// faction at level 80 for custom
|
||||
// servers).
|
||||
// makeRMTPrevent — 4 anti-RMT rules (LevelGated 30+
|
||||
// for any gold trade, Gold cap for
|
||||
// new accounts, AuditLogged for
|
||||
// all trades > 1000g, mandatory
|
||||
// delay placeholder).
|
||||
static WoweeTradeRules makeStandard(const std::string& catalogName);
|
||||
static WoweeTradeRules makeServerAdmin(const std::string& catalogName);
|
||||
static WoweeTradeRules makeRMTPrevent(const std::string& catalogName);
|
||||
};
|
||||
|
||||
} // namespace pipeline
|
||||
} // namespace wowee
|
||||
Loading…
Add table
Add a link
Reference in a new issue