This record describes API changes in 1.9 Alpha 1.

Custom Properties

In API 45 we introduce the concept of custom properties, which supersedes the older concepts of data, static data, and global data.

Any type may define one or more custom properties. Imagine, for example:

<ShipClass unid="&scTestShip;"
      <Global id="myGlobalProperty">"foo"</Global>
      <Data   id="myObjProperty">"bar"</Data>

(typGetProperty &scTestShip; 'myGlobalProperty) -> "foo"
(typSetProperty &scTestShip; 'myGlobalProperty "another")
(typGetProperty &scTestShip; 'myGlobalProperty) -> "another"

(setq testShipObj (sysCreateShip &scTestShip; ...))
(objGetProperty testShipObj 'myObjProperty) -> "bar"
(objSetProperty testShipObj 'myObjProperty "testing")
(objGetProperty testShipObj 'myObjProperty) -> "testing"

<Global> and <Data> are two kinds of properties. The following kinds are defined:

<Definition>: Evaluated at engine load-time; cannot be changed.
<Constant>: Evaluated at game-create time; cannot be changed.
<Global>: Evaluated at game-create time; stored on type.
<Variant>: Evaluated at object-create time; cannot be changed.
<Data>: Evaluated at object-create time; stored on object.
<DynamicGlobal>: Evaluated at get-time; available on type.
<DynamicData>: Evaluated at get-time; available on object.


Properties are inherited as appropriate.


In general, custom properties are meant to replace older concepts of data, static data, and global data. They are particularly useful when the properties are publicly accessible and documented. For example, we use rpg.shipBrokerInventory to define the ship building criteria for ship brokers.

Instead of using static data, use either <Definition> or <Constant>. <Definition> is perfect for values that are always the same from game to game (e.g., the value of Pi). Use <Constant> if you might want different values in different games (e.g., if you use random to generate the constant). NOTE: There is no penalty for using <Constant> even if the value is the same across games.

Use <Global> when you want to store data on a type. Use <Data> is you want to store data on an object. In other words, if you want to store data that will be the same for all (e.g.) Antares-II freighters, then use <Global>. If you want each freighter instead to potentially have different data, use <Data>.

Use <Variant> when you want to generate a different value for each object instance, but you don't want to data to change.

Use <DynamicGlobal> and <DynamicData> for volatile data that needs to be recomputed every time the caller asks for it.

Keep properties orthogonal. That is, the value of a property should not depend on another property. Otherwise, callers will have to remember to coordinate setting multiple properties.

Unknown Items

Starting in API 45 you can specify multiple unknown item types for a given item. For example:

<ItemType UNID="&itHiroShieldOptimizer;"
   name=         "Hiro's shield optimizer"
   attributes=   "info, minorItem, notForSale, shieldEnhance"
   unknownType=  "&itUnknownROM_A;, &itUnknownROM_B;, &itUnknownROM_C;"
   description=  "One of Hiro's first creations..."

Notice that we're specifying three unknown types: Unknown ROM A, Unknown ROM B, and Unknown ROM C.

In this example, when Hiro's shield optimizer spawns (either in a shop or as random treasure), the engine picks one of the three unknown types at random (A, B, or C).

The unknown description for the optimizer will come from whichever unknown type was picked. For example, let's assume type B was picked. The player will see the unknown name, description, level, etc., from B.

When the player identifies the ROM (by using it or by analyzer), they will see the true name. In the future, if Hiro's optimizer spawns again, and if it randomly chooses type B, then the player will see the true name (because type B has been identified).

But if Hiro's optimizer spawns as type A or C, then the player will see an unknown item (until those variants are identified).

Item Lists

Unknown items of different unknown types will not collapse together. For example, if there are two unknown Hiro's ROMs, one of type A and one of type C, then they will appear as two separate items (potentially with different names).

Once an item is identified, they will all collapse into a single entry, as long as there are no other difference between them.


This feature is backwards compatible with previous versions. If you have an item with a single unknownType, it should behave identically to prior version.

In general, different unknown types should have different name lists. That is, the names for unknown type A should be different from unknown type B, otherwise the player may not understand why they are treated differently (i.e., identifying one doesn't identify the other).

Use multiple unknown types when you want an item to continue to be unknown even after one or two versions have been identified. In-game we assume that the visible marking of an item do not completely correlate with its true nature. A ROM can have any label, regardless of its content, so just because we saw a ROM with label "Foo Bar" doesn't necessarily mean that all "Foo Bar" labelled ROMs have the same content.

Conversely, an unknown device such as a jumpdrive is unknown because the player doesn't recognize it. Once identified, the player should be able to identify all future jumpdrives. Even here there are exceptions, however: if devices are custom-created then perhaps different devices with the same function will look different.

Buying Unknown Items

In API 45 you can specify that a station selling items always show the true name of any item:

<Action id="actionBuyAutons">
   (scrShowScreen gScreen &dsRPGCommoditiesExchangeBuy; {
      checkMilitaryID: True
      showActualItem: True

The option showActualItem: True means that items for sale will always be shown with their true name.

If the player buys one of these items, they will be identified (and all future items of that unknown version will be known).


In general you should use this feature when you want to encourage players to buy items (i.e., when the trade off for buying an item, vs. finding/looting, is appropriate). In-game we assume that official shops will tell you what you're buying.

Nevertheless, some shops should sell unknown items "as-is", meaning the player has no guarantees about what they're actually buying. In those cases, there should be a corresponding benefit (usually a lower price) to make the mechanic viable.

Ship Classes

New Properties

  • frequency
  • frequencyRatio
  • maxArmorClassName
  • stdArmorClassName
  • viewportSize


You may specify a frequency for a ship class. This will be used when randomly selecting ships to build at a ship broker. Example:

<ShipClass ...

Item Types

New Properties

  • hp: You may now access the hp property on any armor item, not just installed ones.
  • role: The role property is used by TransData for categorization. It has no effect on game-play.
  • unknownType


  • repeating and repeatingDelay may now be specified at the weapon level (this allows for repeating launchers).

Dock Screens

<GetDockScreen> and <GetGlobalDockScreen>

<GetDockScreen> and <GetGlobalDockScreen> return a struct describing the screen to show. If you need to pass a data element to the screen, you may add a data field:

      data: {
         missionObj: theMission

Starting in API 45 you can specify data elements directly in the main struct and the entire struct will be passed in to the screen. For example:

      missionObj: theMission


Dock screens now get an <OnObjDestroyed> event when an object is destroyed:

<DockScreen ...>


Mission Arcs

You may specify a mission arc for a mission type to guarantee that missions will be given out in a certain order. For example:

<MissionType ...

In the above example, the mission is part of the underworldArc and is assigned the ordinal 2. If there is another mission marked underworldArc:1, then it would appear before 2. Conversely, a mission marked underworldArc:3 would appear after 2.

System Level

Starting in API 45 we honor the level specified in a mission and make sure that it is not randomly created in a system outside its level. You may always manually create a mission (with msnCreate) regardless of system level.

Auto Accept

In API 45, autoAccept= replaces noDecline:

<MissionType ...

The above is the same as noDecline="true". When the mission is given, we automatically accept and exit the dock screen.

You may also specify autoAccept="acceptAndContinue" to continue with the dock screen (e.g., to see the accept reply).

autoAccept="none" is the same as noDecline="false".


Properties from SFX

When calling sysCreateEffect, the effect is created as a space object. In API 45 You may call objGetProperty and objSetProperty to access the underlying effect properties. For example, if you create an <Orb> effect that way, you can access all Orb properties.


  • Add anchorObj to gData
  • Add overlayType to gData


Effects created with sysCreateEffect can have a loop="true" parameter to specify that the effect should continue.


  • Added shell style
  • Added cloudShell style
  • Added dim animation
  • Added opacity property
  • Added secondaryOpacity property


New Properties

  • Added attributes property for systems.
  • Added sizePixels for all objects; returns the size of the object in pixels.
  • Added type property for all objects.

New Functions

  • typIncProperty

Changed Functions

  • fmtNumber now accepts massKg and massTons.
  • msnRegisterForEvents and objRegisterForEvents can take a list of objects.
  • random with no parameters now returns a random double from 0 to 1.0.
  • sysCreateEncounter now returns the set of ships created.
  • Added P criteria to unvFindObject to select objects known to the player.

Changed Events

  • <OnGlobalUpdate> now fires every 30 ticks (instead of every 15). This makes it consistent with all other update events.
relanat 25 Jun 2019:

Some way of accessing all the custom and other properties would be very handy for debugging and testing. There are a couple of tickets around already about this sort of thing.

(...GetProperty theSource '*)

or similar.
Probably not needed for the 'cannot be changed' properties.