Echo Hollow

Gender-Bending Interactive Stories! :D

User Tools

Site Tools


smutbook:classes:persistence:persistentobject

PersistentObject

Extends: Nothing

The PersistentObject is the class from which all of the more complex persistent data types are derived. People, Apparel, Transformable attributes, Inventories of various sorts, and many other classes of objects, are all are ultimately derived from PersistentObject.

Usage Notes

Subclassing PersistentObject

TODO

PersistentObject Behavioral Differences vs. Regular Objects

TODO

  • Deleting a property resets it to whatever was set in the defaults or class definition, rather than actually deleting it. If you want to legitimately delete a property, just set it to 'undefined'.
  • Funny business with subclass constructors.
  • Don't use strict equality because objects may be reallocated differently between game moments, because of the way SugarCube's game state history works.

Static Properties/Functions

Two static utility functions are defined on PersistentObject. These are called through the global class name rather than through specific instances of objects.

PersistentObject.define( id, objectClass=PersistentObject, defaults={}, allowRedefine=false )

Defines the default data for a PersistentObject (or subclass thereof) within your game. PersistentObject.define() must only be called at initialization time, from story javascript or initialization passages. The results of trying to use this function after the game has started are undefined.

All PersistentObjects (and subclasses) must be defined using this method before they can be used within the game. See the Tutorial for a better explanation of all of this.

  • Type: Static Function
  • Arguments:
    • id: the Persistence ID of the object being defined.
    • objectClass: the class of the object being defined. PersistentObject or subclass thereof.
    • defaults: a mapping of property names to data for the object's default data. Records may only contain simple data types, arrays, and PersistentObjects (or subclasses thereof). Non-persistent objects and symbols are not allowed.
    • allowRedefine: if true, the object may be redefined. This is used internally and you probably shouldn't mess with it unless you are sure of what you are doing.
  • Returns: An instantiated instance of the object that was defined.
  • Throws: Error if the object is being redefined (and allowRedefine=false), if the previously defined object does not have a valid class associated with it, or if a defaults record contains a non-array object or symbol.

Example:

SmutBook.PersistentObject.define( "joe", SmutBook.Person.Man, {
	"name":               "Joe",
	"lastName":           "Blow",
	"inventory.contents": [ "revolver" ],
	"apparel.contents":   [ "boxers", "jeans", "tshirt", "socks", "tennisshoes" ]
});

PersistentObject.fetch( id, forceClass=undefined )

Given a persistence ID, returns the appropriate instantiated object (a PersistentObject or subclass).

The returned object is not guaranteed to be the same cached object every time, but they will evaluate as .equal() and for all intents and purposes are the “same” object, behaving identically, exposing the same properties, etc. So don't use strict equality when comparing objects. Just don't, ok?

  • Type: Static Function
  • Arguments:
    • id: the Persistence ID of the object being fetched.
    • forceClass: If set, overrides the class associated with the object ID and uses the given class instead. This is used internally and you probably shouldn't mess with it unless you are sure of what you are doing.
  • Returns: An instantiated instance of the object defined with the given id.
  • Throws: Error if the object does not have a valid class associated with it.

Example:

FIXME

Constructor( id )

ALERT! TAKE NOTE! ALERT!

You should never instantiate a PersistentObject directly! Instead, you must define it with PersistentObject.define(), and then either store the result somewhere or re-fetch it with PersistentObject.fetch() when you want to use it.

If you try to instantiate a PersistentObject directly, rather than wrapping it in a call to fetch(), the Proxy object will get confused about what to do with properties that are set in subclass constructors, and you'll have an unhappy day. fetch() wraps things up with some hackery-magic and makes things behave as you'd expect for the most part.

Again, do not ever use “new” to instantiate a PersistentObject. Instead, store the result of PersistentObject.define() somewhere and reference it when needed, or fetch the object by its 'id' with PersistentObject.fetch().

Properties/Functions

.id

This object's Persistence ID, as defined with PersistentObject.define().

  • Type: String
  • Automatic
  • ReadOnly

.parent

This object's parent. For example, the parent of the object with the id “joe.inventory.contents” would be the object with the id “joe.inventory”.

  • Type: PersistentObject (or undefined if the object has no parent)
  • Automatic
  • ReadOnly

.name

The display name of the object, without any article. For example: “Joe”, “ancient relic”, “pair of gloves”.

  • Type: String

.nameIsProper

Set this field to True to suppress the printing of an article in the .aName, .theName, and generic versions of these fields. Useful for proper names, book titles, etc. See the Tutorial for more information.

  • Type: Boolean

.nameIrregularArticle

Set this field to override the default article choice in .aName and generic versions of that field. Setting it back to undefined or null will return things to normal.

  • Type: String

.aName()

The display name of the object, with the correct article prepended. For example: “Joe”, “an ancient relic”, “a pair of gloves”.

If the first character of the .name field is capitalized, the name will be treated as proper, and no article will be prepended. Ie. “Joe”. Otherwise, if the first character of the .name field is a vowel, the “an” article will be prepended. Ie. “an ancient relic”. Otherwise, the “a” article will be prepended. Ie. “a pair of gloves”.

These rules do not always work. For example, “an honorable man” or “a European swallow”. In these cases, the .nameIsProper and .nameIrregularArticle fields may be used to manually specify the behavior of this field.

  • Type: Function
  • Arguments: None
  • Returns: String
  • Throws: Nothing

.AName()

Same as .aName(), but with the first character capitalized.

  • Type: Function
  • Arguments: None
  • Returns: String
  • Throws: Nothing

.theName()

The display name of the object, with the “the” prepended unless the object is proper. For example: “Joe”, “the ancient relic”, “the pair of gloves”.

These rules do not always work. For example, “the European swallow”. In this case, the .nameIsProper field may be used to manually specify the behavior of this field.

  • Type: Function
  • Arguments: None
  • Returns: String
  • Throws: Nothing

.TheName()

Identical to .theName(), but with the first character capitalized.

  • Type: Function
  • Arguments: None
  • Returns: String
  • Throws: Nothing

.genericName

This is the generic non-detailed name of the object, without any article. This name is used when the item can be detected, but its exact details are unavailable. For example, the genericName is used when an article of apparel is “printing through” an article of thin but non-transparent apparel on a more outer layer. It might also be used when interacting with objects in the dark, where you can feel what they are but cannot see specific details.

  • Type: String

.genericNameIsProper

Same as .nameIsProper, but operates on the genericName instead.

  • Type: Boolean

.genericNameIrregularArticle

Same as .nameIrregularArticle, but operates on the genericName instead.

  • Type: String

.aGenericName()

Same as .aName(), but operates on the genericName instead.

  • Type: Function
  • Arguments: None
  • Returns: String
  • Throws: Nothing

.AGenericName()

Same as .AName(), but operates on the genericName instead.

  • Type: Function
  • Arguments: None
  • Returns: String
  • Throws: Nothing

.theGenericName()

Same as .theName(), but operates on the genericName instead.

  • Type: Function
  • Arguments: None
  • Returns: String
  • Throws: Nothing

.TheGenericName()

Same as .TheName(), but operates on the genericName instead.

  • Type: Function
  • Arguments: None
  • Returns: String
  • Throws: Nothing

.image

A detail image name for the object (used in object details displays, and in inventory thumbnails if no thumbnail is defined.

  • Type: String

.thumbnail

A thumbnail image name for the object (used in inventory displays). By default, it just returns the value of .image, but you can override it in subclasses or set it in PersistentObject.define() to use a thumbnail image that is different from the main detail image above.

  • Type: Getter returning String

.description

FIXME unimplemented

The name of a passage to display with the detail description of the object.

By default it will use some variant of the object id (FIXME what exactly?), but this can be overridden to make multiple objects use the same description passage.

  • Type: String
  • Optional

.inventoryCategory

The inventory category of this object. Used for inventory sorting. Case-sensitive. If falsy, then category is assumed to be “Other”.

  • Type: String
  • Required (if the item can be picked up or worn by the player)

.equals( o )

Overridden to compare object id fields rather than references.

.toString()

Overridden to return this.aName.

.clone()

Overridden to grab an instantiated copy of the object via PersistentObject.fetch().

.toJSON()

Overridden to provide a reviveWrapper that grabs an instantiated copy of the object via PersistentObject.fetch().


smutbook/classes/persistence/persistentobject.txt · Last modified: 2023/08/08 18:39 by lee