Creature Properties

From Dragon Age Toolset Wiki
Jump to: navigation, search
Scripting

The creature property system is the heart of the rules engine and defines all the numerical values that make up a character in Dragon Age.

Detailed Description

Properties are 32-bit floating point values associated with every combat capable creature in the game (Creature Type field in the toolset). They are used by engine, scripting and UI to make up and display the RPG ruleset of the game.


Property Types

There are 3 types of properties that abstract the most common types of statistics found in an RPG:


PROPERTY_TYPE_SIMPLE

Simple properties are 32 bit floats that can hold a single value and that generally are not modified or influenced by other properties. Examples include Experience, Level or the number of unspent talent points a character has.


PROPERTY_TYPE_ATTRIBUTE

Attributes are a moderately complex set of values encapsulating a single character stat. They have three fields that are independently tracked in the engine and are accessible from scripting:

  • Base - A character's unmodified base value, usually only modified during level up and character creation. This number is displayed as a white number on the character sheet.
  • Modifier - A float32 that holds the sum of all effect based modifications to the property. This number is shown as a red (if negative) or green (if positive) number on the character sheet.
  • Total - The sum of the base and modifier fields along with any in engine modifications done to the property in C++ (for speed reasons) as defined by the engine link field. When reading this field, the engine will always clamp the return values between Min and Max, even though it stores the full, unmodified number internally.


Example:

A level 1 warrior with 15 strength, a buff that grants +2 strength and a shield that has a +1 strength enhancement would be stored as as:

  • Base: 15
  • Modifiers: 3
  • Total 18

PROPERTY_TYPE_DEPLETABLE

Depletables represent the most complex type of stats usually found in an RPG, used for Health and Mana. In addition to all fields present on an Attribute, they have an additional 'Current' field.

  • Current - This is the character's current value in this stat, which can be between Min and Max and can exceed Total.

Additionally, just like attributes, the EngineLink field defines some hardcoded behavior in the engine such as creating the link between the 'rengeration rate' properties.

Example:

A level 1 warrior with 14 Con and 100 base health and a +5 health ring would store health who was at full health before getting hit for 20 points of damage:

  • Base: 100
  • Modifiers: +5
  • Hidden Engine Modifiers: +20 (5 points for each point in CON after 10).
  • Total: 125
  • Current: 105

Hidden Engine modifiers can not be modified (obviously, they're in C++), but can be disabled by setting the EngineLink field to 0. They exist purely to speed up stats accessed with high frequency (DAScript has a 7-15x overhead per instruction compared to native code).

Property Definitions

The two dimensional data array defined in Properties.xls defines numerical values that exist on every creature in the game. All properties are float32 and all rules logic of the game is based on floating point math. This dynamic data driven approach to rules relevant stats is new to Dragon Age: Origins and makes the engine extremely flexible for Designers. It enables the game to have a rules logic that is almost completely softcoded in script and data.

The following is an excerpt from the 2da that lists all rows present in the initial ship version of Dragon Age: Origins but only shows the most important columns. Note that DLC or expansion content may be overriding individual lines in the 2da.

ID Stat Type Min Max Comment
int string string float float comment
0 INVALID INVALID 0 0
1 Strength ATTRIBUTE 0 1000 STR Attribute
2 Dexterity ATTRIBUTE 0 1000 DEX Attribute
3 Willpower ATTRIBUTE 0 1000 WIL Attribute
4 Magic ATTRIBUTE 0 1000 MAG Attribute
5 Cunning ATTRIBUTE 0 1000 CUN Attribute
6 Constitution ATTRIBUTE 0 1000 CON Attribute
7 Health DEPLETABLE 1 9999 Hit Points
8 Mana_Stamina DEPLETABLE 0 9999 Mana or Stamina, based on class
9 Attack ATTRIBUTE 0 1000 Attack Power
10 Defense ATTRIBUTE 0 1000 Defense
11 Armor ATTRIBUTE 0 1000 Armor Mitigation Potential
12 DamageScale ATTRIBUTE 1 10 Based Damage Scaling (for difficulty settings and ranks)
13 SpellPower ATTRIBUTE 0 1000 Spellpower (Max(MAG-10,0)+Effects)
14 Regeneration_Health ATTRIBUTE 0 50 Health Regeneration Rate (Explore Mode) per tick.
15 Level SIMPLE 0 99 Current Character Level.
16 Displacement ATTRIBUTE 0 100 Chance to outright evade any physical attach attempt (aka Dodge)
17 Inventory_Size SIMPLE 0 1000 Inventory Slot size (on party)
18 AI_BEHAVIOR SIMPLE 0 1000 Selected AI Behavior
19 Experience SIMPLE 0 186001 Experience Points
20 Flanking_Angle ATTRIBUTE 0 180 The angle at which this creature is able to flank an enemy (default is 90)
21 Melee_Crit_Modifier ATTRIBUTE -100 200 The +melee crit modifier
22 Missile_Shield ATTRIBUTE 0 100 Chance to avoid missiles (shields and some spells increase this)
23 Ranged_Crit_Modifier ATTRIBUTE -100 200 The +ranged crit modifier
24 Ranged_Aim_Speed ATTRIBUTE -3 6 The character's speed bonus or penality when aiming with ranged weapons
25 BaseAttackRating SIMPLE 0 1000 The creature's cached base attack rating
26 BaseDefenseRating SIMPLE 0 1000 The creature's cached base defense rating
27 CurrentClass SIMPLE 0 31 The creature class (index into cla_base.xls)
28 Regeneration_Health_Combat ATTRIBUTE 0 20 The creature's health regeneration rate (per tick) in combat.
29 Regeneration_Stamina ATTRIBUTE -20 50 The creature's stamina regeneration rate (per tick) in explore mode.
30 Regeneration_Stamina_Combat ATTRIBUTE -20 20 The creature's stamina regeneration rate (per tick) in combat mode.
31 AttackSpeedModifier ATTRIBUTE 0 1.5 The creature's universal melee attack speed modifiers (used by haste, momentum, etc.)
32 Resistance_Mind ATTRIBUTE -100 100 Mental Resistance.
33 Resistance_Physical ATTRIBUTE -100 100 Physical Resistance.
34 Attribute_points SIMPLE 0 100 Holds any unspent attribute points the creature has. If this is != 0, the UI shows the levelup button.
35 Skill_points SIMPLE 0 100 Holds any unspent skill points the creature has. If this is != 0, the UI shows the levelup button.
36 talent_spell_points SIMPLE 0 100 Holds any unspent talent points the creature has. If this is != 0, the UI shows the levelup button.
37 Background SIMPLE 0 10 The character's origin (index into backgrounds.xls).
38 specialization_points SIMPLE 0 2 Holds any unspent specialization points the creature has.
39 DamageBonus ATTRIBUTE -100 100 Universal physical attack damage bonus on the creature.
40 Threat_Decrease_Rate SIMPLE -1000 1000 The rate at which the creature's threat rating decays.
41 Fatique ATTRIBUTE -25 250 The creature's current Fatigue (% increase of ability cost).
42 Damage_Resistance_Fire ATTRIBUTE -100 75 The creature's damage resistance to fire. All fire damage is reduce by %.
43 Damage_Resistance_Cold ATTRIBUTE -100 75 The creature's damage resistance to cold. All cold damage is reduce by %.
44 Damage_Resistance_Electricity ATTRIBUTE -100 75 The creature's damage resistance to lightning. All lightning damage is reduce by %.
45 Damage_Resistance_Nature ATTRIBUTE -100 75 The creature's damage resistance to nature. All nature damage is reduce by %.
46 Damage_Resistance_Spirit ATTRIBUTE -100 75 The creature's damage resistance to spirit. All spirit damage is reduce by %.
47 Damage_Shield_points ATTRIBUTE 0 9999 Magical, damage mitigating shield (all damage types) on the creature. Creature immune to damage until the shield is depleted.
48 Damage_Shield_strength ATTRIBUTE 0 100 The maximum amount of damage the creature's magical shields can absorb (not used yet.)
49 Damage_OffHand ATTRIBUTE 0 9999 Display only cache of creature's weapon damage potential. This value is only used to marshal data into the UI, it does not have any rules implications.
50 Damage_MainHand ATTRIBUTE 0 9999 Display only cache of creature's weapon damage potential. This value is only used to marshal data into the UI, it does not have any rules implications.
51 Healing_Effect_Factor ATTRIBUTE 100 200 Percentage modifier of how effective healing is on the creature. Blood magic does NOT use this field, it is coded in effect_heal_h instead.
52 Spell_resistance ATTRIBUTE 0 100 Creature 'hostile magic resistance'. % Chance to avoid any hostile magic.
53 AP_BONUS ATTRIBUTE -100 100 Armor Penetration bonuses are stored her.
54 CriticalRange ATTRIBUTE 0 200 The 'range' which critical hits use. 150 would mean up to 150% of normal damage.
55 Fire_Damage_Bonus ATTRIBUTE 0 30 Percentage bonus to all fire damage dealt by the user (spells, staves, etc.)
56 Spirit_Damage_Bonus ATTRIBUTE 0 30 Percentage bonus to all spirit damage dealt by the user (spells, staves, etc.)
57 Cold_Damage_Bonus ATTRIBUTE 0 30 Percentage bonus to all cold damage dealt by the user (spells, staves, etc.)
58 Nature_Damage_Bonus ATTRIBUTE 0 30 Percentage bonus to all nature damage dealt by the user (spells, staves, etc.)
59 Electricity_Damage_Bonus ATTRIBUTE 0 30 Percentage bonus to all lightning damage dealt by the user (spells, staves, etc.)


Words of Caution

Properties.xls is the most integral and powerful 2da in the game. Any changes to it have profound implications on the game and the chance of breaking existing savegames and introducing unwanted behavior.

Removing Rows It is referenced from many other rules and UI related 2das and removing existing data can have severe consequences, including the invalidation of existing characters. You can NEVER remove rows from this 2da!

Changing Rows Changing rows is not as dangerous as removing them, but still can have severe implications. The m2da system should be utilized to modify individual rows instead of overwriting the entire 2da. Especially the Min, Max and EngineLink columns hold a lot of rules relevant data that might not be obvious on the first glance (e.g. the Max value on 'Experience' defines the maximum XP the game will allow on a character. Any attempt to award more XP from script will silently fail.)

Adding rows: Every row added to this file will reserve several Float32 data fields on every combat capable creature in the game. While a few floats might not sound like a lot, the impact on runtime area memory, savegame size and associated load times can not be overstated. While these issues are more pressing for the console versions of the game, they still do affect the PC version and I strongly advise not to add to this file unless absolutely necessary.

Q&A

Q: Why use Floats instead of integers?

We had initially investigated a structure that would allow creation of typed properties but found the associated overhead and complexity in such a frequently accessed system to be too high to be worth it.

Since much of our system requires floating point values and floats can be easily rounded for display purposes, we decided to use floating point across the board.


Q: Won't floating point math lead to imprecision?

Yes, it can. Certain mathematical operations promote imprecision in floating point values. DA script, like NWScript is only precise for a limited number of digits and any existing imprecision can be magnified by consecutive divisions and other operations.

However, there are mitigating circumstances that make this much less of a problem than it might appear on paper (or fresh from university :)

  • Most frequent calculations retrieve an existing floating point value cached in a property, run a bunch of calculations and then execute the result (e.g. calculating damage). The resulting values are rarely stored so imprecision has little opportunity to build up over time.
  • When writing to values that are displayed as integers on the UI or used as integers in the combat math, we are casting back to integer before storing or computation (e.g. to avoid health from going into the gray realm between 0 and 1).
  • Some engine commands have added security to prevent rounding errors from propagating from script into engine stored values.
  • If you happen to do .004 points damage more during an attack, the gameplay impact is virtually zero, so even if imprecision manages to propagate up to the 3rd decimal, it is still not visible in the game.


Q: Is there anything absolutely hardcoded?

Yes. While nearly all C++ implemented aspects of the rules system can be turned off by removing the associated EngineLink from properties.xls, a few behaviors are not easy to modify or replace by script:

  • Regeneration. While it is technically possible to turn off regeneration by setting all rates to 0, the system can not be modified. One would have to replace it with a scripted, heartbeat like construct to make changes. The reason for this is simple: Regeneration ticks at a high frequency on all combat capable creatures and the cpu time consumed by running this entirely in script is completely unacceptable.
  • Some UI rules are currently hardcoded and although it is possible to control some of the UI through various 2das, replacing the entire UI with a new framework is impossible at this point.