Automatically generate setting-appropriate Story Cards for AI Dungeon, similar to AutoCards.
Important
If you don't know how to install scenario scripts => Scenario Script Installation Guide
Not compatible with AutoCards/SmartCards/etc. or any other automatic Story Card scripts!
Library:
- Copy and paste into your
Librarysection => MagicCards/dist/Library.js
Example:
//#region Magic Cards
// ...
//#endregionBEFORE YOU CONTINUE:
Ensure each hook script does not contain
modifier = (text) => {...}function!Read FAQ section for additional help!
Before:
// Checkout the Guidebook examples to get an idea of other ways you can use scripting
// https://help.aidungeon.com/scripting
// Every script needs a modifier function
const modifier = (text) => {
return { text }
}
// Don't modify this part
modifier(text)After:
// Checkout the Guidebook examples to get an idea of other ways you can use scripting
// https://help.aidungeon.com/scripting
// Don't modify this partInput:
- Copy and paste into your
Inputsection - Reference: MagicCards/dist/Input.js
/// <reference no-default-lib="true"/>
/// <reference lib="es2022"/>
/**
* - Scripting API: https://help.aidungeon.com/scripting
* - Scripting Guidebook: https://github.com/magicoflolis/aidungeon.js/blob/main/Scripting%20Guidebook.md
* @template {<T extends string | null, S extends boolean>(text: T, stop: S, hookType: "input") => { text: T; stop?: S; }} ModifierFN
*/
const hook = ((currentHook = 'input') => {
if (mc.cache.hook !== currentHook) mc.cache.hook = currentHook;
/**
* ---
*
* - Add your modifier functions into this function
* - **Modifier functions are not called when `mc.cache.generating === true`**
*
* ---
*
* _Examples:_
*
* ```js
* hook((text, stop, hookType) => {
* // For 'Story Arc Engine' by Yi1i1i
* text = onInput_SAE(text);
*
* return { text }
* })
* ```
* @param {...ModifierFN} modifiers
*/
const fn = (...modifiers) => {
mc.modifiers.push(...modifiers);
return mc;
};
return fn;
})();
/* This is your modifier function */
hook((text) => {
if (typeof text === 'string') {
/* Your Script's code goes here */
}
return { text };
});
/* Don't modify this part */
void 0;Context:
- Copy and paste into your
Contextsection - Reference: MagicCards/dist/Context.js
/// <reference no-default-lib="true"/>
/// <reference lib="es2022"/>
/**
* - Scripting API: https://help.aidungeon.com/scripting
* - Scripting Guidebook: https://github.com/magicoflolis/aidungeon.js/blob/main/Scripting%20Guidebook.md
* @template {<T extends string | null, S extends boolean>(text: T, stop: S, hookType: "context") => { text: T; stop?: S; }} ModifierFN
*/
const hook = ((currentHook = 'context') => {
if (mc.cache.hook !== currentHook) mc.cache.hook = currentHook;
/**
* ---
*
* - Add your modifier functions into this function
* - **Modifier functions are not called when `mc.cache.generating === true`**
*
* ---
*
* _Examples:_
*
* ```js
* hook((text, stop, hookType) => {
* // For 'Story Arc Engine' by Yi1i1i
* text = onContext_SAE(text);
*
* return { text }
* // Or return { text, stop }
* })
* ```
* @param {...ModifierFN} modifiers
*/
const fn = (...modifiers) => {
mc.modifiers.push(...modifiers);
return mc;
};
return fn;
})();
/* This is your modifier function */
hook((text) => {
if (typeof text === 'string') {
/* Your Script's code goes here */
}
return { text };
});
/* Don't modify this part */
void 0;Output:
- Copy and paste into your
Outputsection - Reference: MagicCards/dist/Output.js
/// <reference no-default-lib="true"/>
/// <reference lib="es2022"/>
/**
* - Scripting API: https://help.aidungeon.com/scripting
* - Scripting Guidebook: https://github.com/magicoflolis/aidungeon.js/blob/main/Scripting%20Guidebook.md
* @template {<T extends string | null, S extends boolean>(text: T, stop: S, hookType: "output") => { text: T; stop?: S; }} ModifierFN
*/
const hook = ((currentHook = 'output') => {
if (mc.cache.hook !== currentHook) mc.cache.hook = currentHook;
/**
* ---
*
* - Add your modifier functions into this function
* - **Modifier functions are not called when `mc.cache.generating === true`**
*
* ---
*
* _Examples:_
*
* ```js
* hook((text, stop, hookType) => {
* // For 'Story Arc Engine' by Yi1i1i
* text = onOutput_SAE(text);
*
* return { text }
* })
* ```
* @param {...ModifierFN} modifiers
*/
const fn = (...modifiers) => {
mc.modifiers.push(...modifiers);
return mc;
};
return fn;
})();
/* This is your modifier function */
hook((text) => {
if (typeof text === 'string') {
/* Your Script's code goes here */
}
return { text };
});
/* Don't modify this part */
void 0;- General:
- Slash commands:
/MC,/AC,/mc,/ac - Works for any character or location
- Compatible with most AI models
- Slash commands:
- Automation:
- Create story card after
xamount of turns (default: 22) - Summarize created story cards after
xamount of turns (default: 22)
- Create story card after
- Settings:
autoHistory: summarize prior events of Story Cards (default: false)autoRetrieve: retrieve Character and Location names from context + memory (default: false)cooldown: number of turns untilautoRetrieveorautoHistoryare triggered (default: 22)enabled: toggle on/off MagicCards (default: true)hiddenCards: toggle additional cardscharacters: AI instructionscompress: AI instructionsdebug: debug card (readonly)locations: AI instructionsretrieve: AI instructions*: Your custom AI instructions (not implemented)
useSmallModel: toggle on/off use of large AI models (default: true)
Important
Does not follow original AutoCards syntax
/MC Name; [Details]/AC Name; [Details]
Example:
/MC Aaron; creator of MagicCards
/AC Leah; creator of AutoCards
"Details" is optional
/MC VeyneInput Commands:
/MC [Input Command]
/AC [Input Command]
Example
/MC retrieveretrieve/get=> force entry check (retrieve)toggle/enable/disable=> toggle MagicCardsreset/restart/restore=> restore to default settingsclear/clr/cls=> clear the current entry being generated (debug command), use if you encounter any errors during generationsummarize/compress=> force summarize all created story cards (compress)
Important
During card generation all modifier functions are not called
This should not cause any issues as long as you don't rely on scripts which need to be called every turn
All functions are exposed and can be easily used.
// Constant should already exist once installed
const mc = new MagicCards(); // or globalThis.mc
// Array of created StoryCards
for (const card of mc.magicCards()) {
console.log( card ); // StoryCard
}
// Create a new story card
const sc = mc.StoryCard({keys: 'foo', entry: 'bar'});
// { card: StoryCard }
console.log( sc.card );Check if "MagicCards" is installed:
Important
This value is not cached:
info.actionCountis 3 =>mc.installedis true- User rewinds action below 3 =>
mc.installedis false
// Constant should already exist once installed
const mc = new MagicCards(); // or globalThis.mc
console.log( mc.installed ); // booleanTemporarily disable:
- This disables MagicCards for the entire turn
- You can set this value anytime to halt MagicCards
// Constant should already exist once installed
const mc = new MagicCards(); // or globalThis.mc
// Not required but recommended
if ( mc.installed ) {
// Stored settings and `state.MagicCards`
const cache = mc.cache;
cache.disabled = true;
}
// or
// Stored settings and `state.MagicCards`
const cache = mc.cache;
cache.disabled = true;Get "calculated" actionCount:
// Constant should already exist once installed
const mc = new MagicCards(); // or globalThis.mc
console.log( mc.actionCount );Check if "MagicCards" exists:
if ( typeof globalThis.MagicCards !== 'undefined' || typeof globalThis.mc !== 'undefined' ) {
// Your code goes here
}
// or
if ( globalThis.MagicCards || globalThis.mc ) {
// Your code goes here
}Do I have to remove the modifier functions?
As strongly I recommend you do, technically you do not if you are willing to edit MagicCards code base.
IMPORTANT: Doing this removes MagicCards control on each hooks modifier function
- Find (Ctrl + F) the
#modifier()function in yourLibrary - Make the following changes
#modifier() {
const modifier = () => { /* ... */ };
//#region Edit this region
// BEFORE
globalThis.modifier = modifier;
Object.freeze(globalThis.modifier);
// AFTER
globalThis.mcModifier = modifier;
Object.freeze(globalThis.mcModifier);
//#endregion
return this;
}- In your
modifier()functions, make the following changes:
const modifier = (text) => {
globalThis.mcModifier(); // or whatever name you gave it
// self-repair
const currentHook = 'input'; // edit to correspond with the current hook
if (mc.cache.hook !== currentHook) mc.cache.hook = currentHook;
/* Your Script's code goes here */
return { text, stop }
}Can I remove the modifier functions in general?
Important
This removes MagicCards "self-repair" feature
Yes! Simply copy + paste this code into each hook:
/* Yup, it's just one line */
void 0;How do I enable autoRetrieve + autoHistory globally?
Make the following changes in the "SETTINGS" Story Card:
autoHistory: true
autoRetrieve: true
useSmallModel: falseHow do I change "X" setting for "Y" Story Card?
In the "Notes" section of the created Story Card.
Available options:
sync: boolean
autoHistory: boolean
defaultCooldown: numberAll options:
sync: boolean
autoHistory: boolean
defaultCooldown: number
cooldown: number
summary: stringsync: automatically syncautoHistory/defaultCooldownwithautoHistory/cooldownfound in the SETTINGS cardautoHistory: togglecompressfor this card, must haveuseSmallModelset to falsedefaultCooldown: default number of turns untilcompressis triggeredcooldown: number of turns untilcompressis triggeredsummary: prior events, automatically added at the end of triggered Story Cards asEvents: ...
When is MagicCards disabled?
- If
info.actionCountis below 3 - If
mc.cache.disabledis true, can be programmatically changed / set - If user inputs an AI instruction (not case sensitive):
[system: ...],<s> ... </s>,<system> ... </system>,## ...,**...**
Which modifier functions are UNSUPPORTED by hook function?
- Functions named
AutoCards,SmartCards, orMagicCards Async,Generator, orPromisetype functions
// All will throw an error
hook(async () => { /* ... */ });
hook(() => {
return Promise.resolve().then(() => text)
});
hook(AutoCards);
hook(MagicCards);
hook(SmartCards);What return values are SUPPORTED by hook function?
Objects,Arrays, orFunctionswhich return either or
hook((text, stop) => {
return { text, stop }
});
hook((text, stop) => {
return [ text, stop ]
});
hook((text, stop) => {
return () => {
// or [ text, stop ]
return { text, stop }
}
});
// Not recommended
hook('Hello World!'); // will change text to this value