Skip to content

External Character Integration

mewcodex edited this page Sep 5, 2026 · 4 revisions

External Character Integration

English | 简体中文

AutoAnthony does not replace a custom character framework. Your mod continues to register its character, pool, cards, derivatives, relics, and multiplayer model IDs in its normal way.

Register the character host

const string profileId = "my_watcher:autoanthony";

ExternalComponentCharacterApi.Register(
    new ExternalComponentCharacterRegistration(
        ProfileId: profileId,
        BalanceArchetype: GeneratedCharacter.Regent,
        EnergyIconPrefix: "watcher"));

The balance archetype selects existing legality and value conventions; it is not the profile identity. Different custom characters may reuse the same archetype because their profile IDs remain distinct.

Register the normal component package with IncludeInUltimateChaos: true (the default). AutoAnthony adds its full reviewed source catalog to the shared weighted Ultimate pool and automatically derives the external profile's UnlockComponentRoles=true view. Use ComponentKeywordPolicy to opt into exactly the native keywords and keyword upgrades the character supports; profile IDs prevent two characters sharing an archetype from leaking rules. Custom keyword IDs have separate base/add/remove allow-lists, so an external profile can expose only the custom keywords and upgrade transitions that its card models actually support.

If the character participates in Archaic Tooth or Dusty Tome, pass an IExternalAncientRelicAdapter in the registration. It identifies the character's players, decides whether each relic is overridden, and returns the two canonical Ancient cards.

Declare fixed card slots

The game ModelDb discovers concrete model types, so declare one concrete class per maximum generated slot:

abstract class WatcherChaosCard : ExternalChaosCardModel
{
    protected sealed override string ComponentProfileId => "my_watcher:autoanthony";
    public sealed override CardPoolModel Pool => ModelDb.CardPool<WatcherCardPool>();
}

sealed class WatcherChaosCard000 : WatcherChaosCard
{
    protected override int Slot => 0;
}

Continue for every stable slot your pool can expose. Do not create model types dynamically after ModelDb startup.

Register the optional runtime host after the character identity and before definitions are first read:

ExternalComponentCharacterApi.RegisterRuntime(
    new ExternalComponentCharacterRuntimeRegistration(
        ProfileId: profileId,
        CardCount: 82,
        CardTypeForSlot: WatcherChaosCardRegistry.TypeForSlot,
        IsRunActive: () => WatcherChaosRun.IsRunActive,
        CardPool: () => ModelDb.CardPool<WatcherCardPool>()));

This removes the need to intercept AutoAnthony's triggered-operation executor or its private Colorful Philosophers pool list. API-v2 adapters remain binary compatible and can migrate independently.

Install run definitions

At new-run creation or save restoration, build complete definitions and install them in contiguous slot order:

ExternalComponentCharacterApi.InstallDefinitions(profileId, definitions);

Every definition must:

  • use slots 0..N-1 without gaps;
  • carry a card whose Character equals the registered balance archetype;
  • contain one validated RuntimeSpec per operation;
  • use stable portrait/effect identifiers that the owning mod can restore.

Every shell type also needs at least one standalone, structured, localized, executable positive component in its own catalog. This is used by bounded generation fallback; AutoAnthony never borrows an Ironclad operation for an external profile. A profile that enforces Special X cards additionally needs a fixed numeric Attack or Skill that can be converted safely.

Call ExternalComponentCharacterApi.ClearDefinitions(profileId) when the run is discarded or fully cleaned up.

Who owns what?

AutoAnthony provides generation, upgrades, rendering, operation interpretation, and generated Power persistence. The character mod owns when generation happens, how many cards each rarity gets, source art/effects, snapshot storage, network authority, and card-pool exposure.

The owning mod must register generator, runtime, optional presentation, and custom-keyword packages before the first profile/card query. It must also serialize the complete definition list and distribute the host's authoritative list to clients; the API verifies the contract but cannot create the owning mod's save or network field.

At multiplayer run start, use ComponentRunSettingsApi.TryResolveMultiplayer(modifiers, out settings) so all peers use every host-owned generation option. Character combat hooks should call ComponentTriggerApi.FirePlayerAsync or FireCardAsync; generation UIs and Surprise-mode integration can use ComponentGenerationProgressApi and ComponentSurpriseApi instead of reflecting into internal classes.

The subscribed Watcher 0.9.25 uses direct CharacterModel, CardPoolModel, and CardModel subclasses plus manual multiplayer ModelId registration. This is why the API accepts normal model types and stable IDs rather than BaseLib or RitsuLib objects. See the repository's WatcherComponentAdapter.cs.txt for a compact adapter skeleton.

Clone this wiki locally