Skip to main content

Weapon data and optics

ROCK already resolves the equipped weapon's physical and record-authored evidence. Consume these snapshots instead of re-scanning the scene graph or reimplementing classification in every addon.

queryEquippedWeaponClassificationV1 · slot 33

bool queryEquippedWeaponClassificationV1(
RockProviderWeaponClassificationV1* outResult);

Returns the current equipped weapon's coarse size class, raw weapon-keyword mask, form ID, weapon generation, confidence, source, and provenance.

The output must have the exact current size. Returns false when the provider is unavailable or no equipped weapon can be classified.

Size classes:

  • Melee;
  • Pistol;
  • Rifle;
  • Heavy.

Classification source and current confidence:

SourceMeaningConfidence
KeywordOne or more recognized WeaponType* keywords.1.0
WeightFallbackPhysical/mesh fallback when authored tags were absent.0.65
DefaultConservative default classification.0.35
NoneNo usable classification.0.0

keywordFlags is deliberately a mask, not a single enum. A weapon can be both Rifle and Shotgun, for example. Prefer the most specific flag your feature understands, then fall back to sizeClass.

Provenance flags identify keyword evidence, mesh-bounds fallback, and whether the result is generation-bound.

RockProviderWeaponClassificationV1 weapon{};
if (RockProviderApi::inst->queryEquippedWeaponClassificationV1(&weapon) &&
weapon.valid != 0) {
const bool shotgun = hasWeaponKeywordFlagV1(
weapon.keywordFlags,
RockProviderWeaponKeywordFlagV1::Shotgun);
// Pick shotgun-specific behavior, otherwise use weapon.sizeClass.
}

getWeaponEvidenceDetailCountV1 · slot 10

std::uint32_t getWeaponEvidenceDetailCountV1();

Returns the number of current generated weapon evidence rows, or 0 when unready/no rows. Current public maximum is eight.

copyWeaponEvidenceDetailsV1 · slot 11

std::uint32_t copyWeaponEvidenceDetailsV1(
RockProviderWeaponEvidenceDetailV1* outDetails,
std::uint32_t maxDetails);

Copies up to maxDetails rows and returns the number copied. Returns 0 for a null buffer, zero capacity, unready provider, or no data.

Each row describes one generated collision/evidence body:

  • body ID and weapon generation;
  • public part kind plus reload/support/socket/action semantic roles;
  • fallback grip-pose ID;
  • local generated bounds and total point count;
  • source name;
  • installed OMOD and attach-point form IDs when known;
  • classification provenance (NameToken, SlotAnchor, RigAnchor, or AttachmentEvidence);
  • legacy interaction/source root identity witnesses.

Prefer the record-authored OMOD/attach identity and semantic enum fields. Never dereference the root witnesses.

getWeaponEvidenceDetailPointCountV1 · slot 12

std::uint32_t getWeaponEvidenceDetailPointCountV1(
std::uint32_t bodyId);

Returns the local generated mesh point count for the evidence body, or 0 if the body is absent/stale. Public output is bounded to 252 points per detail.

copyWeaponEvidenceDetailPointsV1 · slot 13

std::uint32_t copyWeaponEvidenceDetailPointsV1(
std::uint32_t bodyId,
RockProviderPoint3* outPoints,
std::uint32_t maxPoints);

Copies local game-unit mesh points for one evidence body. Returns the copied count, or 0 for invalid buffer/capacity, stale body identity, or unavailable data. Associate them with the same weaponGenerationKey as the detail row.

Use bounds for broad decisions; copy the full cloud only when your feature actually needs geometry.

getWeaponEmitterCountV1 · slot 37

std::uint32_t getWeaponEmitterCountV1();

Returns the current count of discovered flashlight, laser, and reticle emitters, or 0 when unavailable. Maximum is 32.

copyWeaponEmittersV1 · slot 38

std::uint32_t copyWeaponEmittersV1(
RockProviderWeaponEmitterV1* outEmitters,
std::uint32_t maxEmitters);

Copies value-only emitter rows. Each row includes:

  • kind: Flashlight, Laser, or Reticle;
  • source: live effect geometry or an authored add-on node;
  • weapon-local transform and forward vector;
  • effective active and node visible state;
  • whether effect state is actually known;
  • add-on value, OMOD, attach-point, source name, and weapon generation.

active == 0 means “known inactive” only when EffectStateKnown is set. An add-on marker without a live effect can have unknown effect state.

Use TransformValid and DirectionValid independently. Do not assume a visible marker means its effect is active.

getScopeSightStateV1 · slot 67 · callback-only

RockProviderResultV1 getScopeSightStateV1(
std::uint64_t ownerToken,
RockProviderScopeSightStateV1* outState);

Requires ScopeSightState and the game-thread callback boundary. Returns the current equipped optic state without requiring the consumer to traverse weapon nodes.

Fields include:

  • frame, publication sequence, weapon form/generation, and broader generations;
  • Available, Active, MenuOpen, anchor/bounds validity, native overlay validity, and direct-transition requirement flags;
  • activation source: native geometry, ROCK geometry, or manual input;
  • native overlay index;
  • weapon-local anchor and sight bounds;
  • matching sight/scope body, OMOD, and attach-point identities.

Returns TargetUnavailable when there is no current scope/sight snapshot, WrongThread outside the callback boundary, or standard validation/ owner/capability/readiness errors.

ManualDirectTransitionRequired is a coordination signal: the current optic cannot rely solely on the ordinary native geometry transition. It is not permission to manipulate arbitrary native menu or render state.

getWeaponCompositionStateV1 · slot 68

RockProviderResultV1 getWeaponCompositionStateV1(
std::uint64_t ownerToken,
RockProviderWeaponCompositionStateV1* outState);

Requires WeaponComposition. This synchronized value query is not callback-only.

Returns:

  • weapon form/generation;
  • compositionSignature for change detection;
  • number of entries;
  • aggregate semantic coverage mask;
  • missing-coverage mask;
  • publication sequence.

In semanticCoverageMask, bit N corresponds to public RockProviderWeaponPartKindV1 ordinal N. missingCoverageMask instead uses the composition entry's stableIndex: a bit means an active entry had no matching semantic evidence row.

Treat compositionSignature as an opaque equality token. Re-read entries when it changes; do not persist or decode the hash.

Returns TargetUnavailable when no current composition exists.

copyWeaponCompositionEntriesV1 · slot 69

RockProviderResultV1 copyWeaponCompositionEntriesV1(
std::uint64_t ownerToken,
RockProviderWeaponCompositionEntryV1* outEntries,
std::uint32_t maxEntries,
std::uint32_t* outEntryCount);

Requires WeaponComposition. Copies up to 64 installed composition rows. Zero capacity permits a null data pointer and reports count 0; use the state call's entryCount to size a buffer.

Each entry provides OMOD form ID, attach-point form ID, stable index, semantic coverage bits, and flags:

  • Active;
  • Disabled;
  • AttachPointResolved;
  • SemanticEvidenceMatched.

The stable index is stable within the current composition snapshot, not across weapon generations.

Example: cache weapon metadata by generation/signature

struct WeaponCache
{
std::uint64_t generation{0};
std::uint64_t compositionSignature{0};
RockProviderWeaponClassificationV1 classification{};
std::array<RockProviderWeaponCompositionEntryV1, 64> entries{};
std::uint32_t entryCount{0};
};

bool refreshWeaponCache(std::uint64_t ownerToken, WeaponCache& cache)
{
RockProviderWeaponCompositionStateV1 state{};
if (RockProviderApi::inst->getWeaponCompositionStateV1(
ownerToken, &state) != RockProviderResultV1::Ok) {
cache = {};
return false;
}

if (cache.generation == state.weaponGenerationKey &&
cache.compositionSignature == state.compositionSignature) {
return true;
}

RockProviderWeaponClassificationV1 classification{};
if (!RockProviderApi::inst->queryEquippedWeaponClassificationV1(
&classification)) {
cache = {};
return false;
}

std::uint32_t copied = 0;
const auto result = RockProviderApi::inst->copyWeaponCompositionEntriesV1(
ownerToken,
cache.entries.data(),
static_cast<std::uint32_t>(cache.entries.size()),
&copied);
if (result != RockProviderResultV1::Ok) {
cache = {};
return false;
}

cache.generation = state.weaponGenerationKey;
cache.compositionSignature = state.compositionSignature;
cache.classification = classification;
cache.entryCount = copied;
return true;
}

This gives reload, scope, handling, UI, or analytics addons a shared weapon identity without scanning live objects themselves.