-
Notifications
You must be signed in to change notification settings - Fork 0
Authoring a Component Package
This page builds the smallest useful external catalog. A production integration should derive its recipes from a manually reviewed decomposition of the character's native cards.
using ChaosCardGenerator;
var enterCalmSpec = new OperationRuntimeSpec(
OperationRuntimeSpec.CurrentSchemaVersion,
Opcode: "watcher_stance",
Variant: "enter_calm",
Target: "self",
SourceZone: "none",
DestinationZone: "none",
CardFilter: "any",
Flags: [ComponentSemanticFlags.Beneficial,
ComponentSemanticFlags.ScalableReward,
ComponentSemanticFlags.PowerFoundation],
Values: [new RuntimeValueSlot("amount", 1)]);
var enterCalm = new ComponentAtom(
Template: "watcher:enter_calm",
Scope: OperationScope.NonTargeted,
ChineseText: "进入平静。",
RequiresSingleTarget: false,
CardReference: CardReferenceRequirement.None)
{
SemanticId = "watcher/enter_calm/0",
RuntimeSpec = enterCalmSpec
};Opcode, Variant, flags, value-slot IDs, condition IDs, and trigger IDs must be lowercase ASCII identifiers.
Template, profile, package, and semantic IDs must be stable non-empty ASCII strings. Never encode runtime decisions
in ChineseText or EnglishText.
Useful semantic flags include Beneficial, Negative, Restricted, EnemyDamage, PowerFoundation,
ScalableReward, and SelfCardMovement. Use the constants on ComponentSemanticFlags; do not infer these facts
from a Template name or localized sentence.
-
api_scalable_reward: numeric generation may scale this positive effect. -
api_power_foundation: the effect may establish a valid Power card. -
api_negative: classify the operation as a downside when custom pricing is handled elsewhere.
var recipe = new IroncladCardRecipe(
Id: "WatcherCalmExample",
ChineseTitle: "静心",
Cost: 1,
Type: GeneratedCardType.Skill,
Target: TargetMode.Other,
OriginalRarity: GeneratedRarity.Common,
Tags: [],
Atoms: [enterCalm],
TriggerOwners: [-1],
EnglishTitle: "Centering");
var catalog = new ImmutableComponentCatalog(
GeneratedCharacter.Regent,
[recipe]);TriggerOwners[i] is -1 for a top-level operation or the zero-based index of the trigger that owns operation i.
Every recipe atom must also exist in the component catalog. Semantic IDs must be unique.
For a reusable trigger/payoff pair, keep both atoms independent and express only the edge in TriggerOwners:
var triggeredRecipe = recipe with
{
Atoms = [afterEvent, reusablePayoff],
TriggerOwners = [-1, 0]
};The payoff retains its immediate RuntimeSpec and per-unit valuation. The trigger's relative cadence scales it during
whole-card valuation. A compatible event-target trigger may supply the enemy for a reusable targeted payoff such as
T:Poison. Do not encode “that enemy” as a second wording-specific effect.
Do not split a transaction that must capture a selected card, target, current value, or future choice before firing. Also keep nonlinear count conversions atomic when neither half has a stable standalone value—for example, Target-Vulnerable-to-Strength.
const string profileId = "my_watcher:autoanthony";
var request = new ComponentProfileRequest(
profileId,
GeneratedCharacter.Regent, // balance/legality archetype only
unlockComponentRoles: false);
var profile = new ComponentGenerationProfile(
id: profileId + ":normal",
character: GeneratedCharacter.Regent,
unlockComponentRoles: false,
shellCatalog: catalog,
componentCatalog: catalog,
nameCatalog: catalog,
occurrenceFactory: () => ComponentApi.CreateNativeOccurrencePolicy(catalog),
valuePolicy: ComponentApi.DefaultValuePolicy);
ComponentPackageApi.Register(new ComponentPackageRegistration(
PackageId: "my_watcher:autoanthony:components",
Request: request,
Profile: profile,
Localizations:
[
new ComponentLocalizationRegistration(
"watcher/enter_calm/0",
"进入平静。",
"Enter Calm.")
],
Valuations:
[
new ComponentValuationRegistration(
"watcher_stance",
"enter_calm",
new EnterCalmValuation())
]));shellCatalog controls source shell distributions, componentCatalog controls selectable mechanics, and
nameCatalog controls source names. They may be different catalogs. The occurrence factory must return a fresh,
pool-scoped policy instance.
For numeric or named entities, use named placeholders such as [[amount]], [[damage]], [[energy:energy]], or
[[token]] in ComponentLocalizationRegistration. Every placeholder must bind to a RuntimeSpec value/text slot.
LocalizedTexts remains only for API v2 source compatibility.
sealed class EnterCalmValuation : IComponentValuation
{
public int Estimate(ComponentValuationContext context) => 500;
}Values are hundredths of one point of ordinary single-target damage: 500 means five damage-equivalent. Use
context.Value("slot") or FirstExplicitFixedValue() for rolled values. See
API Reference for downside pricing and multiplicity metadata.
var generator = new RandomCardGenerator(request, stableIntegerSeed, balancedValues: true);
GeneratedCard card = generator.Generate(GeneratedRarity.Common);The owning mod chooses seed derivation and rarity counts. Use a stable hash such as SHA-256; never use
string.GetHashCode() for multiplayer or persisted seeds.
Source · Steam Workshop · AutoAnthony 0.3.32 · API v3