Learn how to create and modify content for Aeternitas 18+ Edition
Aeternitas 18+ Edition features a powerful modding system that allows you to extend and modify the game in almost any way imaginable. Mods are JavaScript files that run in a sandboxed environment with full access to the game's modding API.
Mods run in an isolated execution context using new Function(), providing a level of sandboxing. However, mods have full access to the game state through the modAPI object. Always load mods from trusted sources.
loadmod in the game.js file from your computermods or mod to open the mod menuA mod is a JavaScript file that receives a modAPI object:
modAPI.displayOutput({
success: true,
message: "Hello from my mod!"
});
When mods are loaded, the game enters "MODDED MODE":
save modded to save your modded game stateload modded to load a modded savemodAPI.gameDirect reference to the game instance. Use with caution - prefer API methods when available.
modAPI.addItem(itemId, itemData)Adds a new item to the game.
Parameters:
itemId (string): Unique identifier for the itemitemData (object): Item propertiesItem Properties:
{
name: "Item Name",
description: "Item description",
takeable: true,
consumable: false,
heals: 0,
encumbrance: 1,
value: 10,
weapon: false,
damage: 0,
armor: false,
defense: 0,
magical: false,
lightSource: false,
readable: {
lore: "Text content"
},
openable: false,
container: false,
fragile: false,
hidden: false
}
Example:
modAPI.addItem("magic_sword", {
name: "Magic Sword",
description: "A glowing blade that pulses with energy.",
takeable: true,
weapon: true,
damage: 15,
encumbrance: 3,
magical: true,
value: 100
});
modAPI.modifyItem(itemId, itemData)Modifies an existing item. Properties are merged with existing data.
Example:
modAPI.modifyItem("mailbox", {
description: "A mailbox. [MODIFIED BY MY MOD]"
});
modAPI.removeItem(itemId)Removes an item from the game.
modAPI.addRoom(roomId, roomData)Adds a new room to the game world.
Room Properties:
{
name: "Room Name",
description: "Room description",
exits: {
north: "room_id",
south: "another_room",
east: "yet_another_room"
},
items: ["item1", "item2"],
hiddenItems: ["secret_item"],
entity: "npc_id",
visited: false,
locked: false,
dark: false,
gatheringResources: {
harvest: {
materials: ["herb", "wood"],
maxUses: 5,
uses: 5,
exhausted: false
}
}
}
Example:
modAPI.addRoom("my_custom_room", {
name: "Custom Room",
description: "A room created by my mod!",
exits: {
north: "west_of_house"
},
items: ["magic_sword"],
visited: false,
locked: false,
dark: false
});
modAPI.modifyRoom(roomId, roomData)Modifies an existing room.
modAPI.removeRoom(roomId)Removes a room from the game.
modAPI.addEntity(entityId, entityData)Adds a new NPC/entity to the game.
Entity Properties:
{
name: "Entity Name",
description: "Entity description",
gender: "male",
peaceful: true,
health: 50,
maxHealth: 50,
damage: 5,
defense: 2,
drops: ["item1", "item2"],
fleeChance: 0.3,
tamable: false,
merchant: false,
inventory: ["item1"],
prices: {
"item1": 10
},
relationship: 0,
friendshipLevel: 0,
romanceLevel: 0,
relationshipStage: "stranger",
currentLocation: "room_id",
favoriteGifts: ["item1"],
dialogue: {
greeting: "Hello!",
topics: {
"topic": "Response text"
}
},
aiRoutine: {
schedule: [
{time: 6, location: "room_id", behaviors: ["behavior1"]}
]
}
}
Example:
modAPI.addEntity("my_npc", {
name: "Mod NPC",
description: "A friendly NPC created by my mod.",
peaceful: true,
health: 50,
maxHealth: 50,
currentLocation: "my_custom_room",
relationship: 0,
relationshipStage: "stranger",
dialogue: {
greeting: "Hello! I'm from a mod!",
topics: {
"mod": "This mod adds cool features!",
"help": "I can help you with modding!"
}
}
});
modAPI.modifyEntity(entityId, entityData)Modifies an existing entity.
modAPI.removeEntity(entityId)Removes an entity from the game.
modAPI.addRecipe(recipeId, recipeData)Adds a new crafting recipe.
Recipe Properties:
{
name: "Recipe Name",
description: "Recipe description",
materials: ["item1", "item2"],
result: "result_item",
skill: "alchemy",
skillLevel: 5,
discovered: false
}
Example:
modAPI.addRecipe("magic_potion", {
name: "Magic Potion",
description: "A potion that restores health.",
materials: ["herb", "water"],
result: "healing_potion",
skill: "alchemy",
skillLevel: 3
});
modAPI.addCommand(commandName, handler)Adds a new custom command.
Handler Function:
function handler(target) {
return {
success: true,
message: "Command output"
};
}
Example:
modAPI.addCommand("hello", (target) => {
return {
success: true,
message: "Hello from my mod!"
};
});
modAPI.overrideCommand(commandName, handler)Overrides a base game command. Return null to use default behavior.
Example:
modAPI.overrideCommand("look", (target) => {
const game = modAPI.game;
if (game.currentRoom === "my_custom_room") {
return {
success: true,
message: "You see a custom room with special mod content!"
};
}
return null;
});
modAPI.onCommand(callback)Hooks into all commands before they execute.
Callback Function:
function callback(command) {
return null;
}
Example:
modAPI.onCommand((command) => {
if (command.toLowerCase().includes("test")) {
return {
handled: true,
message: "Command intercepted by mod!"
};
}
return null;
});
modAPI.onTurn(callback)Called every turn.
Callback Function:
function callback(turn, game) {
}
Example:
let turnCount = 0;
modAPI.onTurn((turn, game) => {
turnCount++;
if (turnCount % 10 === 0) {
modAPI.displayOutput({
success: true,
message: `You've taken ${turnCount} turns!`
});
}
});
modAPI.onRoomEnter(callback)Called when entering a room.
Callback Function:
function callback(roomId, game) {
}
Example:
modAPI.onRoomEnter((roomId, game) => {
if (roomId === "my_custom_room") {
modAPI.displayOutput({
success: true,
message: "You enter a special mod room!"
});
}
});
modAPI.onItemTake(callback)Called when an item is taken.
Callback Function:
function callback(itemId, game) {
}
Example:
modAPI.onItemTake((itemId, game) => {
if (itemId === "magic_sword") {
modAPI.displayOutput({
success: true,
message: "The sword pulses with energy!"
});
game.score += 10;
}
});
modAPI.setStartingRoom(roomId)Changes the starting room for new games.
Example:
modAPI.setStartingRoom("my_custom_room");
modAPI.overrideCharacterCreation(handler)Overrides the character creation process.
Handler Function:
function handler(game) {
game.playerName = "Mod Character";
return true;
}
modAPI.setFullConversion(enabled)Marks the mod as a full conversion mod.
Example:
modAPI.setFullConversion(true);
modAPI.overrideSave(handler)Overrides the save system.
Handler Function:
function handler(game) {
return {
customData: "value"
};
}
modAPI.overrideLoad(handler)Overrides the load system.
Handler Function:
function handler(saveData, game) {
}
modAPI.registerGrammar(grammarName, grammarRules)Registers a custom grammar template for the parser.
Example:
modAPI.registerGrammar("pirate", {
greetings: ["ahoy", "arr", "yo ho"],
affirmations: ["aye", "arr", "aye aye"]
});
modAPI.getGrammar(grammarName)Retrieves a registered grammar template.
modAPI.getCommandSlots()Returns the extracted command slots including manner, tone, purpose, condition, and deep semantic intent (Schank's Theory).
Returns:
{
manner: "gently" | null,
tone: "lovingly" | null,
purpose: "to comfort her" | null,
condition: "if she agrees" | null,
closeness: "intimate" | "friendly" | "neutral" | "hostile" | "distant",
mood: "happy" | "sad" | "angry" | "playful" | "serious" | "romantic" | "fearful" | "calm" | "excited" | "bored" | "confident" | "shy" | "grateful" | "jealous" | "guilty" | "proud" | "neutral",
roleIntention: "protector" | "attacker" | "helper" | "companion" | "healer" | "teacher" | "romantic" | "provider" | "leader" | "follower" | "negotiator" | "explorer" | null,
targetIntimacy: "intimate" | "personal" | "social" | "public" | null,
socialRuleViolation: "none" | "minor" | "major"
}
Example:
const slots = modAPI.getCommandSlots();
modAPI.getChainOfIntent()
Returns the chain-of-intent analysis for complex commands with multiple purposes.
Returns:
{
primaryIntent: {
type: "primary",
action: "CONTACT",
original: "grab"
} | null,
secondaryIntents: [
{
type: "secondary",
intent: "PROTECTIVE",
description: "pull her away from danger",
strength: "high"
}
],
combinedIntent: "CONTACT_PROTECTIVE" | null,
intentChain: ["CONTACT", "PROTECTIVE"],
emotionalContext: "concerned" | "caring" | "protective" | "romantic" | "friendly" | "hostile" | null,
socialContext: "public" | "private" | "group" | "one-on-one"
}
Example:
const chain = modAPI.getChainOfIntent();
modAPI.normalizeActionToPrimitive(action)
Maps action synonyms to universal primitives (ATTACK, CONTACT, AFFECTION, MOVEMENT, EXAMINE, TAKE, GIVE, COMMUNICATE, USE, CRAFT, DROP, OPEN, CLOSE, EAT, READ, WEAR, REMOVE).
Parameters:
action (string) - The action word to normalize
Returns: The normalized primitive (e.g., "ATTACK", "CONTACT") or the original action if no match is found.
Example:
modAPI.normalizeActionToPrimitive("smack");
modAPI.normalizeActionToPrimitive("pat");
modAPI.normalizeActionToPrimitive("peck");
modAPI.normalizeActionToPrimitive("unknown");
modAPI.getCommandTense()
Returns the detected command tense ("past", "present", "future", "ongoing").
Using Semantic Intent in Commands
You can use semantic intent analysis to create more nuanced command responses based on the player's emotional state, relationship level, and intent.
Example:
modAPI.addCommand("comfort", (target) => {
const slots = modAPI.getCommandSlots();
const chain = modAPI.getChainOfIntent();
const player = modAPI.getPlayer();
if (chain.secondaryIntents.some(i => i.intent === "COMFORTING")) {
if (slots.closeness === "intimate") {
return {
success: true,
message: "You hold them close, offering warmth and reassurance."
};
} else if (slots.closeness === "friendly") {
return {
success: true,
message: "You offer a friendly pat on the shoulder and words of encouragement."
};
}
}
if (slots.mood === "caring") {
return {
success: true,
message: "You express genuine concern and care."
};
}
return {
success: true,
message: "You try to comfort them."
};
});
modAPI.onCommand((command, target) => {
const normalized = modAPI.normalizeActionToPrimitive(command.split(" ")[0]);
if (normalized === "ATTACK") {
const slots = modAPI.getCommandSlots();
if (slots.mood === "playful") {
modAPI.displayOutput({
success: true,
message: "You playfully strike at them!"
});
} else if (slots.socialRuleViolation === "major") {
modAPI.displayOutput({
success: false,
message: "That would be a serious violation of social norms!"
});
}
}
});
Utility Functions
Display Output
modAPI.displayOutput(message)
Displays a message to the player.
Example:
modAPI.displayOutput({
success: true,
message: "Hello from mod!"
});
Execute Command
modAPI.executeCommand(command)
Executes a game command programmatically.
Example:
modAPI.executeCommand("go north");
Random Number
modAPI.getRandom(min, max)
Returns a random integer between min and max (inclusive).
Example:
const roll = modAPI.getRandom(1, 20);
Player Data
modAPI.getPlayer()
Returns player data object.
Returns:
{
name: "Player Name",
inventory: ["item1", "item2"],
equipment: {weapon: "sword", armor: "leather"},
stats: {str: 10, int: 8, ...},
skills: {alchemy: 5, ...},
currentRoom: "room_id",
money: 100,
health: 50,
mana: 30
}
modAPI.setPlayer(playerData)
Sets player data. Only provided properties are updated.
Example:
modAPI.setPlayer({
money: 1000,
health: 100
});
Game State Access
modAPI.getItems()
Returns all items object.
modAPI.getWorld()
Returns all rooms object.
modAPI.getEntities()
Returns all entities object.
modAPI.getRecipes()
Returns all crafting recipes object.
Best Practices
1. Unique Identifiers
Always use unique, descriptive IDs for your content:
modAPI.addItem("my_mod_sword_v2", {...});
modAPI.addItem("sword", {...});
2. Error Handling
Check if content exists before modifying:
if (modAPI.getItems()["mailbox"]) {
modAPI.modifyItem("mailbox", {...});
}
3. Mod Compatibility
Prefix your mod's content with a unique identifier:
const MOD_PREFIX = "my_mod_";
modAPI.addItem(MOD_PREFIX + "sword", {...});
modAPI.addRoom(MOD_PREFIX + "room", {...});
4. Clean Up
Provide unload functionality if needed:
const addedItems = ["my_mod_sword", "my_mod_potion"];
5. Documentation
Document your mod's features and requirements:
modAPI.displayOutput({
success: true,
message: `
=== My Mod v1.0 ===
Features:
- New items: Magic Sword, Health Potion
- New room: Custom Chamber
- New command: 'mymod'
- Requires: No dependencies
`
});
6. Testing
Test your mod thoroughly:
- Test with and without other mods
- Test save/load functionality
- Test command conflicts
- Test edge cases
Examples
Example 1: Simple Item Mod
modAPI.addItem("modded_apple", {
name: "Modded Apple",
description: "A shiny red apple created by a mod.",
takeable: true,
consumable: true,
heals: 20,
encumbrance: 1
});
modAPI.displayOutput({
success: true,
message: "Modded Apple mod loaded!"
});
Example 2: Custom Room and NPC
modAPI.addRoom("mod_tavern", {
name: "Mod Tavern",
description: "A cozy tavern added by a mod.",
exits: {
north: "west_of_house"
},
items: ["modded_apple"],
entity: "mod_bartender",
visited: false
});
modAPI.addEntity("mod_bartender", {
name: "Mod Bartender",
description: "A friendly bartender from a mod.",
peaceful: true,
currentLocation: "mod_tavern",
relationship: 0,
dialogue: {
greeting: "Welcome to the mod tavern!",
topics: {
"drink": "I serve the finest modded beverages!",
"mod": "This tavern was created by a mod!"
}
}
});
modAPI.displayOutput({
success: true,
message: "Mod Tavern mod loaded! Type 'go mod tavern' to visit!"
});
Example 3: Custom Command with Hook
modAPI.addCommand("modtest", (target) => {
return {
success: true,
message: "Mod test command works! Target: " + (target || "none")
};
});
modAPI.onCommand((command) => {
if (command.toLowerCase().startsWith("modtest")) {
modAPI.displayOutput({
success: true,
message: "[HOOK] Command intercepted!"
});
}
return null;
});
modAPI.displayOutput({
success: true,
message: "Command mod loaded! Try 'modtest'!"
});
Example 4: Turn-Based Event
let modTurnCount = 0;
modAPI.onTurn((turn, game) => {
modTurnCount++;
if (modTurnCount % 5 === 0 && game.health < game.maxHealth) {
game.health = Math.min(game.maxHealth, game.health + 1);
modAPI.displayOutput({
success: true,
message: "[MOD] You feel slightly refreshed! (+1 HP)"
});
}
});
modAPI.displayOutput({
success: true,
message: "Regeneration mod loaded! You'll heal 1 HP every 5 turns."
});
Example 5: Full Conversion Mod
modAPI.setFullConversion(true);
modAPI.setStartingRoom("mod_start_room");
modAPI.addRoom("mod_start_room", {
name: "Modded Starting Area",
description: "You begin your adventure in a modded world!",
exits: {
east: "mod_town"
},
items: ["mod_starter_sword"],
visited: false
});
modAPI.overrideCharacterCreation((game) => {
game.playerName = "Mod Character";
return true;
});
modAPI.displayOutput({
success: true,
message: "Full conversion mod loaded! Starting in modded world..."
});
Troubleshooting
Mod Won't Load
Problem: Mod file doesn't load or shows error.
Solutions:
- Check JavaScript syntax errors
- Ensure file is
.js format
- Check browser console for errors
- Verify modAPI is used correctly
Mod Conflicts
Problem: Mod conflicts with base game or other mods.
Solutions:
- Use unique IDs with prefixes
- Check for ID conflicts before adding content
- Test mod compatibility
- Load mods in different orders
Save/Load Issues
Problem: Modded saves don't work.
Solutions:
- Ensure same mods are loaded when loading save
- Check if mod uses save/load overrides
- Verify mod state is saved correctly
- Use
save modded and load modded commands
Commands Not Working
Problem: Custom commands don't execute.
Solutions:
- Check command name conflicts
- Verify handler returns correct format
- Check if command is overridden
- Test command hook interception
Content Not Appearing
Problem: Added items/rooms/NPCs don't appear.
Solutions:
- Verify IDs are correct
- Check if content is added to correct locations
- Ensure rooms have proper exits
- Verify entities have currentLocation set
API Quick Reference
Content Management
addItem(itemId, itemData) - Add item
modifyItem(itemId, itemData) - Modify item
removeItem(itemId) - Remove item
addRoom(roomId, roomData) - Add room
modifyRoom(roomId, roomData) - Modify room
removeRoom(roomId) - Remove room
addEntity(entityId, entityData) - Add entity
modifyEntity(entityId, entityData) - Modify entity
removeEntity(entityId) - Remove entity
addRecipe(recipeId, recipeData) - Add recipe
Commands
addCommand(commandName, handler) - Add command
overrideCommand(commandName, handler) - Override command
Hooks
onCommand(callback) - Command hook
onTurn(callback) - Turn hook
onRoomEnter(callback) - Room entry hook
onItemTake(callback) - Item take hook
Advanced
setStartingRoom(roomId) - Set starting room
setCurrentRoom(roomId) - Teleport player
overrideCharacterCreation(handler) - Override character creation
setFullConversion(enabled) - Mark as full conversion
overrideSave(handler) - Override save
overrideLoad(handler) - Override load
registerGrammar(grammarName, grammarRules) - Register grammar
getGrammar(grammarName) - Get grammar
getCommandSlots() - Get command slots (including semantic intent)
getChainOfIntent() - Get chain-of-intent analysis
normalizeActionToPrimitive(action) - Normalize action to primitive
getCommandTense() - Get command tense
Utilities
displayOutput(message) - Display message
executeCommand(command) - Execute command
getRandom(min, max) - Random number
getPlayer() - Get player data
setPlayer(playerData) - Set player data
getItems() - Get all items
getWorld() - Get all rooms
getEntities() - Get all entities
getRecipes() - Get all recipes
Support
For modding support:
- Check the test mod (
test_mod.js) for examples
- Review the game's source code for implementation details
- Test your mods in a safe environment before sharing
Happy Modding!
Validate your mod files before loading them into the game
Drop your mod file here or click to browse
Supports .js files