The upgrade system

Matija Hustić edited this page Jun 17, 2015 · 11 revisions
Clone this wiki locally

The basic idea

Upgrades are implemented by

  • first identifying the actor which will be using the modifiable behavior.
  • If the fundamental behavior is already implemented in an actor's trait, consider modifying the trait to work with the upgrade system. Otherwise create a new trait that will implement the fundamental and modified behavior using the upgrade system.
  • The trait, that will define the upgradable behavior, will need to implement the IUpgradable interface.
  • The behavior of the upgradable trait is to be made dependent on some number (usually one, but may be more if deemed necessary) of non-negative (usually small) integer parameters. These parameters are called upgrades in the continuation. Upgradable traits may specify upper bounds for the upgrades to signal absence of modified behavior for out-of-bounds values. Note that these upper bounds are allowed to change in time.

As a simple example, consider implementing a trait that provides upgradable firepower for an armed unit. The used upgrade might be called firepower and its upper bound set to 4. The trait would then use the current value of the upgrade firepower to decide by how much to modify the unit's weapon's damage, e.g.

  • if firepower == 0, do not modify;
  • if firepower == 1, increase by 10%;
  • if firepower == 2, increase by 15%;
  • if firepower == 3, increase by 20%;
  • if firepower == 4, increase by 30%;

For values of firepower > 4 there would be no change of behavior with respect to the case firepower == 4. Thus a constant upper bound should be used to signal the futility (or inability) of further trying to augment the upgrade.

Implementation: upgradable trait

The upgradable trait specifies the names of upgrades it wishes to use through the UpgradeTypes property. It specifies the upper bounds for these upgrades during calls to the function AcceptsUpgradeLevel by saying whether or not the proposed value (passed as an argument) for the upgrade is within the usable range. When any of the upgrades has its value changed, the trait is notified of changes through the UpgradeLevelChanged method.

Note that upgrades are parameters defined on the actor level. Thus at a given point in time all upgradable traits using upgrades with the same name will see the same value of the upgrade (through the notification method).

Examples: upgrade consumers

Upgradable traits are also referred to as upgrade consumers.

  • GainsStatUpgrades trait

    The above firepower example is actually one taken from this trait. Similar functionality is present in this trait using the damage, speed, reload and inaccuracy upgrades.

  • UpgradableTrait class

    This class is imagined as a base class for upgradable traits that might not wish to use the full parameter flexibility as described above, but only wish to depend

    • either on a single non-negative bounded integer parameter defining the trait's modification level,
    • or on a single Boolean parameter defining whether or not the trait is activated.

    The trait's modification level is defined as the sum of values of all upgrades that the trait uses. The latter Boolean parameter is obtained as a function of the modification level. Normally an upper bound for the modification level is specified and is used to reject further increments of the individual upgrades.

  • UpgradeOverlay : UpgradableTrait

    When enabled, changes the palette used to render the actor's sprites.

  • InvulnerabilityUpgrade : UpgradableTrait

    When enabled, makes the actor invulnerable.

  • Cloak : UpgradableTrait

    When enabled, makes the actor invisible.

  • DisableUpgrade : UpgradableTrait

    When enabled, makes the actor immobile.

Implementation: upgrade manager

The upgrades' values are handled exclusively by the actor's UpgradeManager trait. The upgradable traits attached to an actor without this trait will not be used and are considered bogus.

To change the value of an upgrade for an actor, it is necessary to call that actor's UpgradeManager.GrantUpgrade and UpgradeManager.RevokeUpgrade in order to increment or decrement, respectively, the upgrade's value. It is not possible for a calling object to revoke more upgrades than it had granted. Consequently, upgrades will never have negative values.

To temporarily increment the value of an upgrade for an actor, use UpgradeManager.GrantTimedUpgrade. To receive notification on the remaining duration of the timed upgrade, use UpgradeManager.RegisterWatcher.

To check if granting a certain upgrade would leave at least one upgrade consumer with non-violated corresponding upper bound, use UpgradeManager.AcceptsUpgrade.

Examples: upgrade providers

Traits that interact with an actor's upgrade manager are called upgrade providers.

  • GrantUpgradePower trait

    Defines a support power that, when charged, grants upgrades to targeted actors.

  • UpgradeActorsNear trait

    Makes the possessing actor grant upgrades to surrounding actors.

  • GrantUpgrade warhead

    Grants upgrades to actors in the warhead's impact range.

  • GlobalUpgradable trait

    Grants upgrades to possessing actor when certain tech tree prerequisites are met. Requires GlobalUpgradeManager to be defined on the Player actor.