Wasted Potential Studios · Dune: Awakening

Dune merchant integration reference release artwork

Dune merchant integration

Use app:economy to request stock categories, Sales and verified item contributions. Use the retained app:merchant_offers interface for the supported schematic catalog. Both return the ordinary Framework service handle; a queued request is not an acknowledgement that an offer is available.

Install WPS Dune Launcher and WPS Dune Framework as separate dependencies. Keep one Framework runtime. Declare the minimum release that supplies the behavior your mod uses, and validate that exact package before publication. Game version labels are advisory; checked native bodies, reflected interfaces and the current local Singleplayer session determine which operations can run.

Choose the right request

Interface Item selection Meaning of price
app:merchant_offers The retained supported schematic IDs returned by the Kit's items command Integer multiplier of the current item base, from 2 through 2,147,483,647
app:economy contributions Author-verified IDs resolved from their qualified live item table and the game's template lookup Canonical unit reference, from 1 through 2,147,483,647

The schematic interface's published multiplier contract is unchanged. A multiplier of 70,000 has a 70,000-Solari reference when the item base is one. If another mod changes that base to two, the same multiplier produces a 140,000 reference before the game's modifiers. Do not reinterpret existing requests as absolute-price requests.

Economy accepts contributions independently of the shipped WPS item catalog. A valid ID and table path do not create an item template or load a new content package. Your content must already supply a template the game can resolve, and you must verify that players can obtain each offered grade. An author-supplied contribution does not authorize the Framework to expose every item in the game.

Submit an item contribution

Framework = require('../../WPS_Framework/Scripts/api')
local app = Framework.new {id='MyMerchantContent', version='0.1.0'}
local shop, problem = app:economy {
    contributions={{
        id='YourVerifiedItem',
        table='/Game/YourMod/DT_Items.DT_Items',
        price=120, stock=0, currency='Solaris',
        qualities={0,1}, qualityPrices={['0']=120,['1']=180},
        exchange=true, sellable=false, category='custom'
    }}
}
assert(shop, problem and problem.message)

Replace the illustrative item and table with your tested content. Read shop:status() and wait for the acknowledged revision before reporting success. pending and waiting are not success. An unavailable contribution capability leaves that request waiting without disabling unrelated accepted stock or Framework services.

Each request accepts at most 64 distinct contributions. Each item has an explicit dense, unique qualities list of one to six integers from 0 through 5. If qualityPrices is present, use string grade keys and supply a positive integer price for every declared grade, with no additional grades. Without it, each declared grade uses price. stock accepts 0 through 1,000,000; zero is unlimited. currency is Solaris. Optional category defaults to custom and uses a lowercase letter followed by lowercase letters or underscores, up to 64 characters.

exchange defaults to true and requests Buy eligibility. sellable defaults to false and supplies eligibility to a separately requested Sales feature. It does not enable Sales by itself. A Sell-only contribution uses exchange=false, sellable=true and sales=true. Category and Sales requests keep their existing shape. all=true selects all twelve stock categories and Sales; do not combine it with categories or an explicit sales field.

The supported stock categories are ammo, armor, augments, components, consumables, equipment, fuel, ingots, resources, schematics, vehicle_parts and weapons. The built-in category controls use those labels; other contributed category labels remain searchable and visible through All.

The JSON schemas validate portable request documents. Runtime validation also checks case-insensitive duplicate Economy IDs, exact known schematic IDs, live tables, templates and service envelopes. JSON validation cannot establish game compatibility or ownership.

Startup selection Contribution behavior
Stock and Sales A ready owned policy may supply both sides and its verified Buy grades.
Stock without Sales Buy policy may activate; sellable=true does not turn Sales on.
Sales without stock controls A ready Sell-only policy may activate. Managed graded Buy waits for the required stock controls; independent ordinary native offers remain untouched.
Optional policy unavailable The affected contribution waits; unrelated accepted WPS selections remain available.

Ownership belongs to an offer

The Framework coordinates the complete merchant offer, including vendor, Buy or Sell side, item, current source and world. An item ID appearing in the WPS catalog is not proof that WPS owns every offer for that item. Independently supplied offers keep their prices, stock, currencies and native requirements unless a checked service operation owns that exact record.

Agreeing owners can share a contribution; a divergent request cannot silently take over another owner's record. Existing matching offers may be adopted without writing them. Adoption does not grant permission to modify that pre-existing offer later, and withdrawing the last adopted lease leaves the original offer in place. Offers created by the service are removed or restored only while their checked identity and applied values still agree. An external change retains a diagnostic and pending cleanup rather than being overwritten.

Owner identities are opaque and case-sensitive. Do not lowercase, parse or manufacture an owner token. The Framework separates its Economy and schematic services with internal ownerScope values economy and merchant. Diagnostic owner scopes are case-sensitive too. ownerScope, native tickets, snapshot tokens and ownership revisions are implementation metadata, not new fields in app:economy or app:merchant_offers requests. Withdrawing a request from one service does not release the other service's agreeing lease.

Price changes and grade choices

The selected WPS price policy in Framework 1.6.9 retains its original item base, canonical reference and grade ratios. A later change to the live base scales the WPS reference and grade references together. It does not replace the original denominator while leaving old grade prices behind. For example, a reference base of 20, canonical price of 100 and grade price of 150 retain a 1.5 grade ratio. A live base of 40 produces references of 200 and 300 before native modifiers.

An independent contribution keeps its explicitly requested canonical and grade policy on its own proven offer. The native contribution transaction verifies the current base again before deriving a map factor, so an intervening base change cannot commit an obsolete denominator. A contribution policy is not merged into the global WPS catalog by item ID.

Preview and the accepted transaction must use the same checked offer, selected grade and policy revision. If that proof or price changes, the stale action is rejected and the quote needs a refresh before charging. Native quantity, currency, affordability, finite stock, character modifiers, condition, requirements and rejection behavior remain part of the quote and transaction path.

Sales retains the native higher payout and its minimum protection based on half the applicable purchase reference. Preferred-vendor behavior, character and condition modifiers, rounding and currency handling remain in the native quote path; Sales is not a flat multiplication of every item by 0.5. Framework 1.6.9 scopes its saved policy to managed presentation and transactions and does not set the game's global VendorBaselineDemand to implement it. The legacy provider used without saved content retains its established compatibility implementation; do not infer that its internals changed from these saved-policy details.

Supported grade masks are computed from the explicit grade list: bit q means grade q. {0,2} corresponds to mask 5. This is diagnostic metadata; callers continue to submit qualities, not a numeric mask. A safely readable independent descriptor with a native quality outside 0 through 5 retains native handling. It does not make that grade available for WPS preparation or reject the entire storefront. Malformed entries are reported individually.

Saved content and lifecycle

saved=true requires the selection prepared before launch; it never falls back to a different writer. Mount preparation, successful mounting and feature readiness are separate states. Selecting new saved categories requires a restart. A completed mount does not prove that every optional contribution or gameplay path is ready.

Framework 1.6.9 retains original merchant item objects and applies search, category, tier and grade controls to the managed Exchange's permitted source. Ordinary merchants retain their native Buy and Sell controls and lists without WPS search or grade-preview preparation. Native sorting remains in control. Prepared input filters cached records. Trusted native content completions reuse the existing source generation when it is unchanged, so duplicate notifications do not reread the list, describe its items or republish metadata. A genuine native rebuild, native view change, ownership or price-policy revision rebuilds the affected source. Independent content notifications retain a full refresh. No extra snapshot pass or recurring row worker is installed. No additional item-level field is claimed. The original merchant's eligibility and independently added offers remain the boundary of the source.

Rows already at the requested grade retain the native price and do not enter the preview quote bridge. Grade changes retain scoped native quotes and restoration. The native purchase boundary validates and binds the selected GUI item on demand, including its checked offer, grade and displayed price. It then retains the existing fresh transaction quote, quantity, affordability, stock and grant checks. No new public request fields are required.

The internal bridge admits native events on the game thread before entering Lua. It holds checked weak window and world identities, not delayed borrowed callback parameters. Closing a window invalidates its work; a new opening must establish a fresh lifetime. Source, character/world, ownership, policy and observed item-base changes invalidate the affected cache. A price change during preparation discards that incomplete result and waits for a valid content refresh instead of charging from it. These internal mechanisms do not expand the public app:hook contract.

Use handle:update(full_request) for an intentional replacement. Keep the handle while a temporary session loss or cleanup is pending. handle:stop() queues withdrawal; wait for status().state == 'stopped' before closing the app. Independent owned offers follow their checked restoration rules. Loaded saved definitions and their required native guards remain until restart. After a world transition, the service retires the old world's leases without writing through expired objects and validates a new ownership epoch before applying work again.

Verify your content

Use an isolated save and test the exact distributed packages on Steam and Xbox PC when you declare both editions. Check first opening and reopening, Buy/Sell switching, combined filters, native sorting, selected grades, single and large purchases, full inventory, finite stock, wallet totals and save/reload. Include a changed-base test and an independent offer for the same item ID. Confirm that stopping one agreeing owner leaves the other active and that an outside edit is preserved during cleanup.

Package and schema checks establish request shape. Native body checks establish a bounded interface match. Neither establishes delivered items, saved state or frame-time performance. Record those acceptance results separately and describe only the behavior you verified in your release notes.