This document describes API changes for 1.7 Alpha 2.

Scalable Items

Scalable items are items with a variable level. The level can be set at runtime and the properties of the item (e.g., hit points) change depending on the level. The item type defines whether or not an item is scalable and how its properties change with level.

Defining Scalable Item Types

To define a scalable item, simply set the level parameter to a range of levels:

<ItemType unid="..."
   level="3-8"
   ...
</ItemType>

The above XML defines an item type that can be scaled from level 3 to level 8. By default the item is created at level 3, but can be set to any level between 3 and 8.

Items cannot be scaled above level 25 nor below level 1.

Setting an Item's Level

Once an item type has been defined as scalable, you can set the level of an individual item in the following ways:

  • Use (itmSetProperty ...) or (objSetItemProperty ...) to set the level of an item. Obviously, this method will only work for scalable items and within the level range defined by the item type.
  • Add level="..." to an <Armor> or <ArmorSegment> element in a <ShipClass>.

Armor Items

In armor items, the following properties scale:

  • Hit Points scale proportionally to standard scale. Imagine a scalable level 5 armor with 120 hit points. The standard hit points for level 5 armor is 100, so this armor is 20% more than standard. When we scale up, we maintain that proportion. Thus at level 6, the armor has 135 hp + 20% = 162 hit points.
  • Damage Adjustment scales to the level. Imagine a scalable level 5 armor with +50% bonus to blast damage. At level 6, the armor will still have +50% bonus to blast damage. Remember, though, that damage resistance is already relative to level, so the armor will have higher blast resistance at level 6 (but still only +50% relative to standard).
  • Default immunities are applied for the level. For example, armor scaled to level 6 becomes immune to blinding attacks, even if not originally immune. Armor is immune to radiation at level 7, EMP at level 9, and device damage at level 11. NOTE: If the armor has explicit immunities, those are inherited when scaling up, but there is no (current) way to force higher-level armor to not be immune.
  • Regeneration and decay scale proportionally to hit points. That is, when scaling from level 5 to level 6, regeneration (or decay) improves according to the standard scale for hit points. If standard level 6 armor has 30% more hit points than standard level 5 armor, then the armor will regenerate 30% more.
  • Prices scale proportionally to standard scale. If standard level 6 armor costs twice as much as level 5 armor, then the armor will double in price when scaled to level 6. The same applies to repair cost and install cost.

Drive Devices

Drives do not normally scale with levels, so we need to explicitly define the scaling parameters. We implement a <Scaling> element to defined different properties at different levels:

<ItemType unid="..."
      level="1-5"
      ...
      >
   <DriveDevice>
      <Scaling>
         <Stage level="1"   maxSpeed="20"   thrust="100"   powerUse="100"/>
         <Stage level="3"   maxSpeed="25"   thrust="200"   powerUse="200"/>
      </Scaling>
   </DriveDevice>
</ItemType>

In the above example we've defined a drive device that scales from level 1 to 5. The scaling parameters define the properties: for a given level, we use the properties defined by the entry for that level. For example, when scaled to level 3, we use the properties defined for the level="3" stage (maxSpeed="25", etc.).

If no stage matches exactly, we interpolate linearly between the stages above and below. For example, for level 2, we interpolate between the properties for level 1 and level 3.

If there is no stage above, then we simply copy the previous stage. In the example above, levels 4 and 5 are identical to level 3. It is an error to not have a stage below, however. A scalable item that starts at level n must always define a stage of level n.

Like other scalable devices, prices scale with weapon prices.

Cargo Holds

Cargo expansion devices have explicit scaling parameters just like drives:

<ItemType unid="..."
      level="1-5"
      ...
      >
   <DriveDevice>
      <Scaling>
         <Stage level="1"   cargoSpace="50"/>
         <Stage level="3"   cargoSpace="100"/>
      </Scaling>
   </DriveDevice>
</ItemType>

Reactor Devices

Reactors scale along a standard power scale:

  • Power Output scales along the standard power scale, proportionally to initial power. For example, if a given scalable reactor outputs one-half of normal power for its level, then it will continue to output one-half of normal power for all scaled levels.
  • Fuel Capacity scales proportionally to power output scaling.
  • Prices scale along the weapon price scale.

Weapon Devices

The following weapon properties scale:

  • Damage scales along the standard damage scale.
  • Prices scale along the weapon price scale.

Other Item Improvements

Drives Can Enhance Maneuverability

Drive devices can now enhance ship maneuverability:

<ItemType ...
   ...
   <DriveDevice
         ...
         maxRotationRate="6.0"
         rotationAccel="2.0"
         rotationStopAccel="9.0"
         />
</ItemType>

When installed and enabled, the device will increase rotation rate and rotation acceleration up to the level defined (unless already higher).

Device Properties

API 30 adds the following properties to device items. They can be access using objGetItemProperty and objSetItemProperty:

  • 'capacitor: For devices that need to charge up.
  • 'temperature: For weapons that overheat.

Ships

Initial Data

For consistency with stations, a <ShipClass> can now have an <InitialData> element, which is used to initialize object data when a ship is created.

If there is an <InitialData> element in a ship table (e.g., the definition of a station's guards) then the two elements are merged. Data in the ship table will override the ship class only if it has the same ID.

Hero Images

The large ship image shown for player ships is defined in the <PlayerSettings> element. For consistency with stations, we also allow a <ShipClass> to have a <HeroImage> element to define it.

The <HeroImage>, if it exists, overrides the image in <PlayerSettings>.

Dock Screen Customization

API 30 allows a player ship class to customize the look of the dock screen elements. The <PlayerSettings> element can have a <DockScreenDisplay> element, which specifies images and colors to use for the dock screen. The <DockScreenDisplay> element has the following attributes:

  • backgroundImage: The UNID for the background image to use. It should be 1280×528 pixels in size. The default is &rsDefaultDockScreenBkgnd;.
  • contentMask: The UNID for the mask used to paint images. It should be 1280×528 pixels in size. The default is &rsDefaultDockScreenMask;.
  • textBackgroundColor: The RGB color of the background area behind normal text.
  • textColor: The RGB color of normal text in dock screen.
  • titleTextBackgroundColor: The RGB color of the background behind the title.
  • titleTextColor: The RGB color of title and header text.

<OnPlayerLeftShip> Event

This event is raised on a ship when the player switches to another ship. gSource is the old ship; aNewShip is the ship object that we are switching to.

<OnPlayerEnteredShip> Event

This event is raised on a ship when the player switches to it. gSource is the new ship; aOldShip is the previous ship (which could be Nil).

This event is also called when the game is first created.

<OnDataTransfer> Event

When changing ships, we move any stored data ((objSetData ...)) from the old ship to the new ship. This handles some older code which stored things like fleet rank on the ship object.

The <OnDataTransfer> event allows ship classes to prevent this automatic data move. Classes may returns a struct, in which each element represents a data attribute. The value can be set to ignore to prevent data from being transferred. If the value is copy, then we proceed with the copy (as normal).

For example:

<OnDataTransfer>
   {
   myData1: 'ignore
   myData2: 'copy
   }
</OnDataTransfer>

Imagine that the above event is placed on ship B. When the player switches from ship A to ship B, we call <OnDataTransfer> on ship B to decide which data to move from ship A.

myData1 is not moved from ship A to ship B, which means we do not overwrite the data on ship B.

But myData2 is copied from ship A to ship B.

Any data on ship A that is not mentioned in the struct above is copied by default.

Fuel Properties

API 30 adds two new properties to manage fuel:

(objGetProperty shipObj 'fuelLeft) -> Fuel left (in standard fuel rod units)
(objGetProperty shipObj 'maxFuel) -> Fuel capacity (in standard fuel rod units)

The fuelLeft property is settable (and automatically adjusts to stay within the max fuel limit).

Other Properties

  • Added 'powerUse, which returns the number of kilowatts currently being consumed. Compare against 'power to determine the percent of reactor capacity being used.

Missiles

sysFindObject

API 30 now honors the directives in sysFindObject for projectiles. In all cases, this
only works when combined with the m directive, which selects projectiles.

  • The H directive includes only projectiles fired by the source object.
  • The A directive includes only active projectiles. It excludes any projectile that is dead but painting its fade-out animation.
  • The X directive includes only projectiles whose target is the source object.

Particle Effect Weapons

There's a new parameter for particle effect weapons:

minDamage="..."

When a ship is hit with particles, we always do at least the minimum damage, regardless of how many particles actually hit.

Properties

In API 30 we now support the lifeLeft property for projectile, which is the number of ticks left before the projectile expires. This property can be modified with objSetProperty.

Dock Screens

Armor/Device Management Screens

Armor and device management screens are implemented with an item selector control, specified with, for example, type="armorSelector". Previously, the set of items show in a selector depended on the type. For example, type="armorSelector" was hard-coded to show armor segments and shields.

Starting in API 30, we honor the list= parameter in <ListOptions> to control the set of items shown in a selector. For backwards compatibility, screens prior to API 30 will continue to ignore the list parameter.

We've also introduced a new type: type="deviceSelector", which makes fewer assumptions about the types of devices to show. For example, it allows mixing weapons and misc devices (though not armor).

API 30 adds the following parameters to <ListOptions> to control behavior of selectors:

  • Added slotName parameter in <ListOptions> to set label for empty slots (defaults to "device slot").
  • Added noEmptySlots parameter to <ListOptions> to omit any empty slots.

Markers

Starting in API 30 you can make markers visible by setting the style property. This is mostly useful for debugging. For example:

...
(setq markerObj (sysCreateMarker "my marker" pos &svPlayer;))
(objSetProperty markerObj 'style 'smallCross)

The above will draw the marker as a small, yellow cross. Currently, smallCross is the only supported style. Setting the style to nil will make the marker invisible again.

Galactic Map

Station Information

In 1.7 Alpha 2 the galactic map shows summary information for each known station. The summary information is designed to remind the player of the key features of each station (refueling, installing, etc.). By default, this information is generated based on <Trade> definitions.

Individual stations may override this summary information by adding specific <Language> entries:

  • core.mapDescMain: The simplest case is where you want to add a service that is not covered in the <Trade> description. The text for this entry is prepended to any other autogenerated descriptions.

  • Example:

    <Language>
       <Text id="core.mapDescMain">
          "Microsaur training"
       </Text>
    </Language>
    
  • Skipping Trade descriptions: Sometimes you don't want a particular <Trade> service to generate a description. You can add a parameter: noDescription="true" to specify that a particular trade entry should not generate a description. For example:

  • <Trade>
       <Buy ... noDescription="true"/>
    </Trade>
    
  • core.mapDesc: Use this language entry to override the entire autogenerate description. You will be responsible for describing all services.
  • core.mapDescAbandoned: By default, when a station is destroyed, the information text changes to "abandoned". If you wish to provide different text, you may add this language entry.
  • core.mapDescCustom: Station information is designed to be accessed by the player when in a different system. For example, while in St Kats, I might want to see the services in the Dorado system. Since Dorado stations are not loaded, we generate station information solely on the <StationType> state. That is, we do not have access to the gSource object when generating the text in core.mapDesc.

  • This could be a problem if your station changes services based on some runtime state. For example, imagine a station that sells ships, but only if NPC ships are docked. We want to add an if-statement that checks to see if there are any ships before returning the service.

    The core.mapDescCustom language entry is used exactly for this purpose. You may use the gSource variable inside it to check whatever station state you need and then generate appropriate text.

    The language entry will be invoked when you leave the system, so that it is up to date if you ask for information in a different system.

  • core.mapDescAbandonedCustom: This element is the same are core.mapDescCustom, but is invoked only if the station is abandoned.

Other Enhancements

  • Added lightYearsPerPixel= to <SystemMap> type. This value can be a floating point number. It is used only to show a scale when displaying a topology map.

Effects

  • The <Ray> effect now accepts the blendMode parameter.
  • The <Ray> effect's animateOpacity parameter has been renamed to animate. It now supports two values: fade (which was the only value supported by animateOpacity) and flicker, which causes the ray to flicker through various sizes and intensities (similar to the flicker animation for <Orb>).

TransLISP

struct Function

The struct function is used to construct structures; it is analogous to list. The function supports the following syntax:

(struct nil) -> nil
(struct 'a 1) -> { a:1 }
(struct 'a 1 'b 2) -> { a:1 b:2 }

(struct (list 'a 1)) -> { a:1 }
(struct (list 'a 1) (list 'b 2)) -> { a:1 b:2 }

(struct { a:1 }) -> { a:1 }
(struct { a:1 } { b:2} ) -> { a:1 b:2 }

Support for doubles in data increment functions

Functions which increment opaque data now support doubles. For example:

(objIncData gSource 'myVar 1.2)

The above will properly increment by 1.2, whereas before, it would truncate to 1.

Type Timer Events

API 30 adds functions to add timers on arbitrary types. The events get called in any system (unlike object timers). The new functions are:

(typeAddTimerEvent unid delay event)
(typAddRecurringTimerEvent unid interval event)
(typCancelTimerEvent unid event)

Other Changes

  • objGetOverlays now accepts a criteria as a second parameter (optionally).
  • Added scrGetScreen function to return current dock screen.
  • Added scrAddMinorAction to add a minor action to a dock pane.
  • Added join function to easily concatenate a list of strings.
arkheias on 3/2/2016 9:03 PM:

Is there any chance that you might add support for optional libraries in this version?

the_shrike on 3/3/2016 8:20 PM:

Will this let me have an armor that shows up throughout its level band: Eg. Armor A has a level band of 1-4, I go to a shop and find segments of armor A that are level 1, 2 and 4...or would it generate them all at Level 1 and make me need to set up some other way of doing that?

george moromisato on 3/3/2016 8:45 PM:

@the_shrike: Not currently. It will only show up as the lowest level band. But it's a good idea and we need to think of how to support what you're suggesting.

nms on 4/15/2016 7:10 AM:

If damage is the only (performance affecting) property of weapons that scales, scaling weapons won't be very good.

As you upgrade to higher level weapons, you expect DPS to increase by some multiplier. But you also expect to gain a damage type tier every 3 levels. So when you don't, you expect extra damage, and when you do, you expect a smaller (maybe negative) damage change.

In some cases it might be logical for a weapon to be upgradable to a better damage type, probably at specified levels. In others it might not. But either way, the damage increase should take into account whether there's a damage type improvement.