Recent Changes - Search:

Main.SideBar (edit)

PmWiki

UseOfUpgrades

Introduction

In this document we discuss where upgrades might be of use and how such a use could be implemented. We assume that we have an upgrade implementation that provides at least the features described in Upgrades, and therefore at least temporary as well as permanent upgrades and upgrades that apply to all units of a type, all new units of a type or certain units only.

Definition

The term "Upgrade" refers to the fact that some property (such as maximum health) is modified in some way so that it differs from its original value.
When an upgrade is applied the "current" value of a corresponding property might be modified as well, but the upgrade applies to the maximum or minimum values only.

For example an upgrade "health += 100" increases the maximum health of a unit by 100. If that unit had 10 health only out of an initial maximum of 100, then it has a new maximum health of 200 and the actual health may depend on the implementation (it might remain at 10, it might be increased by 100 or it might be increases so that the health/maxhealth factor remains constant, i.e. health=20).

The term "technology" has often been used as a synonym for upgrades in Boson, therefore I am going to define it as well here, as we use it differently. A "technology" is an upgrade that can be researched, for example in a TechCenter. Upgrades that can not be researched (such as "experience") are not called "technology".

Possible upgrades

  • Technologies - upgrades that can be researched
These are always permanent. They always apply to all new units of the types they apply to. They can apply (but dont have to) to existing units of the types they apply to.
  • Experience - upgrades that units can gain by doing their job
These are always permanent. They apply to a single unit only. Certain technologies (or other upgrades) might even cause units to have some "initial" experience, i.e. to have an experience upgrade right after they got produced (a training center might cause such an effect)
  • Motiviation and Moral - upgrades gained by the types of actions of the unit
very similar to experience, but are not permanent. An example would be attacking a civil unit: the "good guys" may get a negative upgrade then, the "bad guys" might have fun at doing so and therefore may get a positive upgrade.
  • Special Item - certain items on the map that can be collected by units
can be any kind of upgrades: temporary, permanent (usually temporary), positive, negative, ...
  • Certain events - such as "it's getting dark"
like Special items this can be any kind of upgrades. But unlike special items, this can happen without the player doing anything.
How do you take care of removing such upgrades? E.g. suppose you have two events: "night" and "day" triggering "Night" and "Day" upgrades. How do you make sure the "Night" upgrade gets removed before the "Day" is applied? - RL
AB: from IRC discussion: From a upgrade-architecture point of view this is easy: removeUpgrade(night); addUpgrade(day);. The concrete implementation might use a "ApplyOnEvent=EventList" entry in an upgrade config and analogously a "RemoveOnEvent=EventList" or a "RemoveBeforeApply=UpgradeList" entry.
  • Presence of a certain unit or unittype on the map
always temporary (lasts only as long as that unit or unittype is on the map). Example may be "sightrange *= 2" when player has a radar, or "health *= 10" when a "general" is on the map.
  • Presence of a certain unit or unittype in range.
Same as "Presence of a certain unit or unittype on the map", but with a certain range. Both may be implemented the same way, by using "infinite range" for the previous one.

Storage

IDs

The last unresolved problem from Upgrades (upgrades architecture) is how to save and load upgrades. In other words: how to assign IDs to the upgrades.

We will most likely require IDs set by the user for the upgrades. I cannot see a way around this, as we cannot load upgrades for a savegame otherwise (unless we would save the whole upgrades to the file, which I do not want).
The reason for why an ID approach is probably required is that we need to implement things like the following: Unit::loadUpgradesFromXML(const QDomElement& root) { for each upgradeElement in root { Upgrade* pointer = retrievePointer(upgradeElement); addUpgrade(pointer); } } That is we need some way to convert a "upgradeElement" into an upgrade pointer. The pointer is provided by some object that has already loaded all upgrades from the relevant files (just like we do it with index.unit files and UpgradeProperties pointers). Probably that object will be an object of the SpeciesTheme class. So we need some kind of SpeciesTheme::upgrade(id) method that takes information (the ID - this may be integer, string, a mixture, or even something else) and returns the corresponding upgrade pointer.
NOTE: if you can imagine a way how we can load the upgrades of a unit without such a method (except of saving the upgrade itself completely as this would prevent version updates), then please speak up, it might fix the problem or at least lead me into a new direction.

If we make use of IDs, then they must be per-file IDs. Demanding that an ID is unique globally is much too much work for a upgrade designer. In order to load upgrades anyway we have several options:

  • If we provide a single SpeciesTheme::upgrade(id) method that provides all upgrades:
    • Encode the file into the integer id. One way would be to use 16 bits for the actual ID and 16 bits for the file ID.
    • Use an ID pair, i.e. do not use "int id" but rather "QString file, int localId". The filename must be relative then, e.g. "species/human/index.technology" and so on.
    • Other possibilities (already discarded, wont be used):
      • Use MD5 of the upgrade (bad: when an upgrade is changed by the upgrade designer, the ID will change, too, making the savegame useless).
      • Use the "index" of the upgrade in a file as localId. Huge advantage: the designer does not need to care about the ID. Even huger disadvantage: When upgrades are re-sorted in the file, the IDs will change.
      • Use the name of the upgrade as ID. Again the designer does not need to care about the ID. But same problem here: when the name is changed (typos, corrections, rewordings, ...) the ID is changed and savegames useless.
  • If we provide multiple SpeciesTheme::upgrade(id) methods, such as SpeciesTheme::technology(id), SpeciesTheme::experienceUpgrade(id), ...
    • Use a simple local id (integer).
    • Instead of multiple methods we could also add a "type" parameter to SpeciesTheme::upgrade() that identifies whether an upgrade is a technology an experience, ...

I think it makes sense to use the "multiple SpeciesTheme::upgrade(id) methods" aproach. We actually need multiple methods, but just two parameters, a "type" (experience,...) and a (local) ID parameter. Therefore Unit::loadUpgradesFromXML() just needs to call SpeciesTheme::upgrade() with two parameters, which can both be read from the XML file.

Edit - History - Print - Recent Changes - Search
Page last modified on July 13, 2005, at 04:07