Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Migration Guide

This document will explain the process of migrating your existing data when new versions of Alter Ego are released.

Upgrading to 2.0.0

Status Effect and Gesture Updates

Many Status Effects and Gestures have been updated. You can copy them from the demo environment. If you don’t want to use the .setupdemo command, you can find a copy here.

General Description Updates

While your spreadsheet should hopefully load just fine, the introduction of the script parser module means that many of your descriptions are likely to be broken now. If you relied on arbitrary code execution in descriptions in the past, some things may be impossible to do now.

Remember to use the parse command to find errors in your descriptions! It will help you find out what needs to be updated.

Item Lists

In version 2.0.0, il tags are now populated automatically whenever the description they’re in is parsed. If there are item tags in your descriptions as they are loaded, Alter Ego will try to remove them every time it parses the description. However, it may not be able to do so perfectly every time.

Important

You should remove all item tags from your descriptions. Mentions of Fixtures and infinite items can stay, but existing item tags may cause item lists to be populated strangely.

Procedurals

Any existing Room Items or Inventory Items whose Prefabs have procedural tags in their descriptions will not be considered to have any procedural selections. As such, they will not be carried over when those items are transformed. If you would like to give them the procedural selections they should have, you will need to manually add the selected named procedural and poss tags to the descriptions of those items.

Puzzle Descriptions

The text of the already solved description should be moved to the new unsolved description column for the following Puzzle types:

  • toggle
  • media

New Default Player Description

With the release of version 2.0.0, a new default Player description has been included. It is as follows:

<desc><s>You examine <var v="this.displayName"/>.</s> <if cond="this.hasBehaviorAttribute('concealed')"><s><var v="this.pronouns.Sbj" /> <if cond="this.pronouns.plural">are</if><if cond="!this.pronouns.plural">is</if> [HEIGHT], but <var v="this.pronouns.dpos" /> face is concealed.</s></if><if cond="!this.hasBehaviorAttribute('concealed')"><s><var v="this.pronouns.Sbj" /><if cond="this.pronouns.plural">'re</if><if cond="!this.pronouns.plural">'s</if> [HEIGHT] with [SKIN TONE], [HAIR], and [EYES].</s> <if cond="this.hasStatus('tired')"><s><var v="this.pronouns.Sbj"/> <if cond="this.pronouns.plural">have</if><if cond="!this.pronouns.plural">has</if> bags under <var v="this.pronouns.dpos"/> eyes.</s></if><if cond="this.hasStatus('exhausted')"><s><var v="this.pronouns.Sbj"/> <if cond="this.pronouns.plural">have</if><if cond="!this.pronouns.plural">has</if> dark bags under <var v="this.pronouns.dpos"/> eyes.</s> <s><var v="this.pronouns.Sbj"/> look<if cond="!this.pronouns.plural">s</if> absolutely **exhausted**.</s></if><if cond="this.hasStatus('delirious')"><s><var v="this.pronouns.Sbj"/> look<if cond="!this.pronouns.plural">s</if> completely **delirious**, like <var v="this.pronouns.sbj"/> <if cond="this.pronouns.plural">have</if><if cond="!this.pronouns.plural">has</if>n't slept in days.</s></if></if><br /><br /><s><var v="this.pronouns.Sbj" /> wear<if cond="!this.pronouns.plural">s</if> <il name="equipment"></il>.</s><if cond="this.getContainedItemsForItemList('equipment').length === 0"><s><var v="this.pronouns.Sbj" /> <if cond="!this.pronouns.plural">is</if><if cond="this.pronouns.plural">are</if> completely naked.</s></if> <s>You see <var v="this.pronouns.obj"/> carrying <il name="hands"></il>.</s> <if cond="this.hasStatus('stinky')"><s><var v="this.pronouns.Sbj"/>'<if cond="this.pronouns.plural">re</if><if cond="!this.pronouns.plural">s</if> a little stinky.</s></if><if cond="this.hasStatus('rancid')"><s><var v="this.pronouns.Sbj"/> smell<if cond="!this.pronouns.plural">s</if> absolutely **rancid**.</s></if> <if cond="this.hasStatus('soaking wet')"><s>Also, <var v="this.pronouns.sbj"/> <if cond="!this.pronouns.plural">is</if><if cond="this.pronouns.plural">are</if> soaking wet.</s></if><if cond="this.hasStatus('wet')"><s>Also, <var v="this.pronouns.sbj"/> <if cond="!this.pronouns.plural">is</if><if cond="this.pronouns.plural">are</if> a bit wet.</s></if></desc>

What every section does is detailed here. It is recommended you update your Player descriptions to fit this template, but you are free to modify it as you see fit.

Important

Old Player descriptions used to use container in their if and var tags to refer to the Player. Every instance of container in Player descriptions should be replaced with this.

Inserting Descriptions into Descriptions

In the past, it was sufficient to insert descriptions into other descriptions by accessing the .description (or similarly named) attribute. However, Descriptions are now objects. As such, this is no longer possible. Now, you must use the parseFor method.

The following list contains several strings on the left side of the arrow (->) and what you should replace them with on the right side of the arrow.

  • .description -> .description.parseFor(player)
  • .correctDescription -> .correctDescription.parseFor(player)
  • .alreadySolvedDescription -> .alreadySolvedDescription.parseFor(player)

New Mirror Styles

The way mirrors reflect Player descriptions has changed, too. It used to be something like this:

<desc><s>You look at your reflection.</s> <var v="player.description.replace(/container./g, 'player.')" /></desc>

However, now it is recommended that you use something like this:

<desc><s>It's a mirror hung on the wall.</s> <s>You can see your reflection in it:</s><br /><s> >>> </s><var v="player.description.parseFor(player)" /></desc>

Finder Module Calls

The finder module has been a core part of descriptions, and that remains the case. However, a few finder functions have changed.

Renamed Data Types

With the release of 2.0.0, Objects have been renamed to Fixtures, and Items have been renamed to Room Items. As such, you should make the following replacements:

  • findObject -> findFixture
  • findItem -> findRoomItem

Updated Function Signatures

findRoomItem has had its function signature changed. It is now:

findRoomItem('ITEM IDENTIFIER OR PREFAB ID', ('location-name'), (Type of Container: 'Fixture' || 'Puzzle' || 'RoomItem'), ('CONTAINER NAME(/INVENTORY SLOT ID)'))

See the following example for how to update calls:

  • findItem('COMFORTER', this.location.name, 'Object: BED') -> findRoomItem('COMFORTER', this.location.id, 'Fixture', 'BED')

Deprecated Attributes

The following properties have been deprecated. They will be listed here along with their replacements:

Common Code Patterns

It is impossible to list all examples of code execution that were used in descriptions prior to 2.0.0. Here are some common patterns, along with their suggested replacements.


let prob = 8; const x = Math.floor(Math.random() * prob); x === 0

Should become:

doWithChance(8) === true

let prob = 500; if (player.statusString.includes('exhausted')) prob /= 50; if (player.statusString.includes('delirious')) prob /= 500; const x = Math.floor(Math.random() * prob); x === 0

Should become:

player.hasStatus('delirious') || doWithChanceModifiedByPlayerStatus(500, player, 'exhausted', 50) === true

game.items.filter(item => item.location.name === container.location.name && item.containerName === `Puzzle: ${container.name}` && !isNaN(item.quantity) && item.quantity > 0).reduce((total, item) => total + item.quantity * item.weight, 0)

Should become:

this.childPuzzle.getContainedItemsWeight()

this.exit[3].unlocked === true

Should become:

this.getExit('FLOOR 2').unlocked === true

const words = ['about','above','across']; words[Math.floor(Math.random() * words.length)]

Should become:

getRandomString(['about','above','across'])

Flags

With the introduction of Flags, many common code patterns in descriptions can be replaced with calls to the finder module’s findFlag function.

Edge Cases

When in doubt, check the writing descriptions tutorial to see if there’s a way to fix your descriptions while retaining the same functionality. All of the articles on data structures also detail their useful methods.