Skip to content

feat(services): price identification by actual items identified #217

Description

@zoeyrose

Outcome

Replace Smith identification's flat NPC-level fee with a bounded work-based
quote and actual-work settlement. The player sees what inventory scope will be
examined and an exact or ranged price; after confirmation, the amount charged
is based on the number of items actually identified. A no-op costs nothing.

This is a future content consumer of
atrinik/classic#264. It is
related to temple service design in #106 but does not block that temple-specific
delivery.

Current behavior

Smith.py
currently prices mass identification as 200 + 50 * NPC level and one marked
item as 50 + 10 * NPC level, regardless of how many eligible items can be
identified.

On confirmation it removes the full fee before calling
CastIdentify().
The script only rejects a missing marked object for the single-item service; it
does not know whether the marked item is already identified, too difficult, or
otherwise ineligible, nor how many objects mass identification actually
changes.

Proposed behavior

  • Query Classic for bounded items_identified work in the exact marked,
    marked-container, or normal inventory scope.
  • Convert the work count into a documented bounded price formula. With current
    deterministic identification rules the range will usually collapse to one
    exact price; if identification later becomes uncertain, the same UI and
    settlement contract can show a genuine lower/upper range.
  • Display scope, eligible count range, minimum/maximum price, provider identity,
    available funds, and maximum possible provider debt before confirmation.
  • Re-query at confirmation. Changes to the marked object, container contents,
    eligibility, provider capability, debt, or price require a fresh quote.
  • Cast through the normal outcome-bearing identification API and calculate the
    final charge from the actual number identified. Zero actual items means zero
    cash and zero debt.
  • Allow explicitly confirmed partial funding through the provider-specific
    credit ledger in feat(server): persist provider-specific service debt classic#267. Existing debt to that smith must be
    repaid before another paid service; other providers are independent.

Provider metadata

Every participating smith needs a canonical authored npc_id for debt and
confirmation identity. Audit whether combat level is a legitimate
identification capability; if not, author a dedicated low-frequency custom
service-rank attribute and register only its typed content extension metadata.
Do not dispatch or persist by display name, map path, interface filename, or
runtime object count.

Acceptance criteria

  • Every Smith service provider is inventoried with a unique stable npc_id
    and an explicit, reviewed capability input.
  • Marked, marked-container, and normal inventory scopes exactly match
    Classic identification behavior; text does not promise recursive or
    otherwise broader identification than the native spell performs.
  • The documented formula produces a bounded minimum/maximum price from the
    queried eligible-item work range, with exact rounding and caps.
  • Preview and confirmation use the same formula and state evidence; drift
    requotes without casting or charging.
  • The final cash plus new debt is calculated from actual items identified,
    never from attempted items or the quote maximum, and cannot exceed the
    confirmed maximum.
  • Already identified, invisible, non-identifiable, over-capability, empty
    container/inventory, and missing-marked-object cases cast nothing and cost
    nothing.
  • Partial and full identification, insufficient funds, partial funding,
    prior provider debt, repayment, repeat confirmation, and provider
    relocation/rename are tested.
  • Existing CastIdentify() callers remain compatible; this service uses
    the work-query/outcome APIs from feat(server): make scripted spell services work-aware classic#264.
  • python3 tools/validate.py, git diff --check, derived Classic server
    tests, an isolated runtime scenario, and repository-required checks pass.

Dependencies and boundaries

Blocked by atrinik/classic#264,
including work queries (#265/#266), actual identification outcomes (#248), and
provider credit (#267).

This issue owns authored Smith pricing, provider metadata, dialogue, and
integration. It does not change identification spell scope or implement the
future Go commerce services tracked by
atrinik/server#52.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Fields

Priority

Medium

Start date

None yet

Target date

None yet

Effort

None yet

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions