Movedefs.lua: Difference between revisions

From Spring
Jump to navigationJump to search
Flozi (talk | contribs)
→speedModMults: 86.0 - unhardcode default pathfinder cost-adjustment and speed-multipliers for squares blocked by *mobile* units
Maddox (talk | contribs)
m Fixed comment about hover class: canHover was removed in 95.0
 
(24 intermediate revisions by 4 users not shown)
Line 7: Line 7:


==Source==
==Source==
The engine source code which parses the data from this file is viewable here: {{sourcelink|file=rts/Sim/MoveTypes/MoveInfo.cpp}}
The engine source code which parses the data from this file is viewable here:  
* {{sourcelink|file=rts/Sim/MoveTypes/MoveDefHandler.cpp}}
 
==Data Types==
{{DataTypes}}


==Details==
==Details==
A mobile unit is assigned a '''MoveClass''' using the <code>movementClass</code> [[Units-UnitDefs#Movement_.26_Placement|UnitDef]] tag. The engine determines the unit's pathfinding based on the properties of the '''MoveClass''', so analogous properties (e.g. <code>FootprintX</code>) in the [[Units-UnitDefs|UnitDef]] should be the same for optimal behaviour.
A mobile unit is assigned a '''MoveClass''' using the {{xtaglink|Gamedev:UnitDefs|movementClass}} tag. The engine determines the unit's pathfinding based on the properties of the '''MoveClass''', so analogous properties (e.g. {{xtaglink|Gamedev:UnitDefs|footprintX}}) in the [[Gamedev:UnitDefs|UnitDef]] should be the same for optimal behaviour.


All '''MoveClasses''' must belong to one of four possible types. A '''MoveClass''' is assigned a type simply by including it within the name string e.g. <code>Tank_MyMoveClassName</code>. Types are used in '''TypeMaps''' of Spring maps, which allow mappers to set per-type speed multipliers.  
All '''MoveClasses''' must belong to one of four possible types. A '''MoveClass''' is assigned a type simply by including it within the name string e.g. <code>Tank_MyMoveClassName</code>. Types are used in '''[[Mapdev:terraintype|TypeMaps]]''' of Spring maps, which allow mappers to set per-type speed multipliers.  


===Types===
===Types===
Line 18: Line 22:
* <code>Tank</code> - A ground based '''MoveClass'''. Identical to <code>Bot</code> other than interaction with '''TypeMaps'''.
* <code>Tank</code> - A ground based '''MoveClass'''. Identical to <code>Bot</code> other than interaction with '''TypeMaps'''.
* <code>Ship</code> or <code>Boat</code> - Are synonyms. All ships / boat '''MoveClasses''' must belong to this type to behave as ships.
* <code>Ship</code> or <code>Boat</code> - Are synonyms. All ships / boat '''MoveClasses''' must belong to this type to behave as ships.
* <code>Hover</code> - All hovercraft '''MoveClasses''' (traverse any depth of water without speed reduction) must belong to this class, as well as having <code>canHover</code> in their [[Units-UnitDefs#Movement_.26_Placement|UnitDef]] to behave as hovers.
* <code>Hover</code> - All hovercraft '''MoveClasses''' (traverse any depth of water without speed reduction) must belong to this class.


==MoveClass Tags==
==MoveClass Tags==
Line 25: Line 29:
|type = string
|type = string
|default = ""
|default = ""
|description = The name of the '''MoveClass'''. Usually passed by the sub-table variable name rather than using the <code>name</code> tag (See [[#Example]]). Must contain "tank", "hover", "ship" or "boat" respectively for non-Bot types.
|description = The name of the '''MoveClass'''. Usually passed by the sub-table variable name rather than using this tag (See [[#Example]]). Prior to 9.50 this had to contain "tank", "hover", "ship" or "boat" respectively for non-Bot types. This is now set using {{taglink|speedModClass}}.
}}
 
{{tag
|name = speedModClass
|type = int
|default = 1
|special = {{new|95.0}}
|description = Determines the speed modifier class used (See [[Mapdev:terraintype]]). Accepted values are <code>0</code> = Tank, <code>1</code> = KBot, <code>2</code> = Hover, <code>3</code> = Ship.
}}
}}


Line 32: Line 44:
|type = int
|type = int
|default = 1
|default = 1
|description = How wide the '''MoveClass''' is in footprint units, left to right. 1 footprint unit = 16 [[elmos]]. Cannot be below <code>1</code>. For mobile units this should be the same as the <code>footprintX</code> of its [[Units-UnitDefs#Movement_.26_Placement|UnitDef]].
|description = How wide the '''MoveClass''' is in footprint units, left to right. 1 footprint unit = 16 [[elmo]]s. Cannot be below <code>1</code>. For mobile units this should be the same as the {{xtaglink|Gamedev:UnitDefs|footprintX}} of its [[Gamedev:UnitDefs|UnitDef]].
}}
}}


Line 39: Line 51:
|type = int
|type = int
|default = footprintX
|default = footprintX
|description = How wide the '''MoveClass''' is in footprint units, top to bottom. 1 footprint unit = 16 [[elmos]]. Cannot be below <code>1</code>. For mobile units this should be the same as the <code>footprintZ</code> of its [[Units-UnitDefs#Movement_.26_Placement|UnitDef]].
|description = How wide the '''MoveClass''' is in footprint units, top to bottom. 1 footprint unit = 16 [[elmo]]s. Cannot be below <code>1</code>. For mobile units this should be the same as the {{xtaglink|Gamedev:UnitDefs|footprintZ}} of its [[Gamedev:UnitDefs|UnitDef]].
}}
}}


Line 46: Line 58:
|type = float
|type = float
|default = 10.0
|default = 10.0
|description = Power of a unit with this '''MoveClass''' to crush features and units. Any features (and units with crushing enabled via [[Lua_SyncedCtrl#Unit_Control|Spring.SetUnitBlocking]]) with a <code>crushResistance</code> less than this value will be crushed on contact (See [[Units-FeatureDefs#General]] and [[Units-UnitDefs#General]]).
|description = Power of a unit with this '''MoveClass''' to crush features and units. Any features with a {{xtaglink|Gamedev:FeatureDefs|crushResistance}} less than this value will be crushed on contact. Any units with crushing enabled via [[Lua_SyncedCtrl#Unit_Control|Spring.SetUnitBlocking]]), in an impact where collider impulse exceeds collidee impulse and whose {{xtaglink|Gamedev:UnitDefs|crushResistance}} is less than this value will also be crushed.
}}
}}


Line 52: Line 64:
|name = maxSlope
|name = maxSlope
|type = float
|type = float
|default = 60.0</code> (<code>15.0</code> for hover types)<code> <!-- ugly! -->
|default = 60.0 (15.0 for hover types)
|description = The maximum steepness of slope a unit with this '''MoveClass''' can climb in degrees. For further details see [[#How_slope_is_determined]].}}
|description = The maximum steepness of slope a unit with this '''MoveClass''' can climb in degrees. For further details see [[#How_slope_is_determined]].}}


Line 64: Line 76:
{{tag
{{tag
|name = avoidMobilesOnPath
|name = avoidMobilesOnPath
|type = bool
|default = true
|description = Do the units attempt to avoid other mobile units when pathing?
* Pro: groups moving without a ctrl-order clump much less
* Contra: groups moving with a ctrl-order are less organized
}}
{{tag
|name = allowTerrainCollisions
|type = bool
|default = true
|special = {{new|96.0}}
|description = Disable this to improve handling of large (>4 x 4) footprint units (See {{mantis|4217}}).
}}
{{tag
|name = allowRawMovement
|type = bool
|type = bool
|default = false
|default = false
|description = Do the units attempt to avoid other mobile units when pathing?
|special = {{new|104.0}}
|description = Enables native "raw move" (straight-line path) support  (See also [[Lua_SyncedCtrl|Spring.SetUnitMoveGoal]] and {{mantis|4412}}).
}}
}}


=== Heat Tags ===
=== Heat Tags ===
These tags are used in unit avoidance. {{tag
These tags are used in unit avoidance.  
 
{{tag
|name = heatMapping
|name = heatMapping
|type = bool
|type = bool
Line 80: Line 112:
|name = heatMod
|name = heatMod
|type = float
|type = float
|default = 0.05
|default = 0.0042
|description = The pathfinder cost modifier that is multiplied by the heat of the current square.
|description = The pathfinder cost modifier that is multiplied by the heat of the current square.
}}
}}
Line 88: Line 120:
|type = int
|type = int
|default = 30
|default = 30
|description = How much heat to place on a square if a path goes through it. ''heat set = max(currentSquareHeat, <code>heatProduced</code>)''.
|description = How much heat to place on a square if a path goes through it. <code>heat set = max(currentSquareHeat, heatProduced)</code>.
}}
 
=== Flow Field Tags ===
These tags are used in unit avoidance.
 
{{tag
|name = flowMapping
|type = bool
|default = true
|description = This enables/disables [https://leifnode.com/2013/12/flow-field-pathfinding/ flow field mapping].
}}
 
{{tag
|name = flowMod
|type = float
|default = 1.0
|description = Multiplied by the objects {{xtaglink|Gamedev:UnitDefs|mass}} for the y-component (up) of the flow vector. No idea what effect this has.
}}
}}


Line 103: Line 152:
|type = float
|type = float
|default = 0.0
|default = 0.0
|description = The maximum depth of water in [[elmos]] the unit can wade through.
|description = The maximum depth of water in [[elmo]]s the unit can wade through.
}}
}}


Line 111: Line 160:
|type = float
|type = float
|default = 10.0
|default = 10.0
|description = The minimum depth of water in [[elmos]] the ship requires to float in.
|description = The minimum depth of water in [[elmo]]s the ship requires to float in.
}}
}}


Line 153: Line 202:
}}
}}


The following tags control the behavior of the unit within the active portion of the curve (depth is greater than minHeight but less than maxHeight). It would be best to simply open up your graphing program of choice and use the provided formula, but if you're scared of graphs you should read the descriptions below:
The following tags control the behavior of the unit within the active portion of the curve (depth is greater than {{taglink|minHeight}} but less than {{taglink|maxHeight}}). It would be best to simply open up your graphing program of choice and use the provided formula, but if you're scared of graphs you should read the descriptions below:


{{tag
{{tag
Line 159: Line 208:
|type = float
|type = float
|default = MAX_FLOAT
|default = MAX_FLOAT
|description =  This is the cap on how severe the depth effect can be. That is, if maxscale is 2, the slowest the unit will go because of depth is half-speed. 4 = a quarter speed, and so on.
|description =  This is the cap on how severe the depth effect can be. For example, lets say that you use a maxScale value of 2. If a unit is at the depth where its scale reaches the max (usually near its maximum depth; with a maxScale value of 2), the slowest it will go is half of its maximum speed. In other words, (maxVelocity / maxScale). Therefore, as another example, a value of 4 would cause the unit's maximum speed (near the units maximum depth) to be 25% of it's maxVelocity.
}}
}}


Line 166: Line 215:
|type = float
|type = float
|default = 0.0
|default = 0.0
|description =  The application of the speed-divider effect is modeled as a quadratic.  This is the "depth-squared" component of that.  That is, a value set here will be applied exponentially as the unit gets deeper... use very small numbers for this one.
|description =  The application of the speed-divider effect is modelled as a quadratic.  This is the "depth-squared" component of that.  That is, a value set here will be applied exponentially as the unit gets deeper, therefore it is best to use very small numbers for this tag.
}}
}}


Line 173: Line 222:
|type = float
|type = float
|default = depthMod
|default = depthMod
|description =  The application of the speed-divider effect is modeled as a quadratic.  This component makes divisor increase linearly with the depth of the unit.  So with a value of 0.1, for example, a unit would go from 1/2 speed to 1/3 speed and 1/3 speed to 1/4 speed each time it goes 10 units deeper.
|description =  The application of the speed-divider effect is modelled as a quadratic.  This component makes divisor increase linearly with the depth of the unit.  So with a value of 0.1, for example, a unit would go from 1/2 speed to 1/3 speed and 1/3 speed to 1/4 speed each time it goes 10 units deeper.
}}
}}


Line 180: Line 229:
|type = float
|type = float
|default = 1.0
|default = 1.0
|description =  The application of the speed-divider effect is modeled as a quadratic.  This is the constant component of the divisor.  If you want a gradual decrease of speed and your minHeight is 0 (the waterline) then this value *must* be 1.  Using less than 1 will cause the unit to go *faster* as it hits the water, and using greater than 1 will cause the unit to abruptly slow down the moment it gets its feet wet.  If you're not using a minHeight of 0, you'll have to adjust this value accordingly to get that same smooth application of the depthMod divider.
|description =  The application of the speed-divider effect is modelled as a quadratic.  This is the constant component of the divisor.  If you want a gradual decrease of speed and your {{taglink|minHeight|0}} (the waterline) then this value '''must''' be 1.  Using less than 1 will cause the unit to go ''faster'' as it hits the water, and using greater than 1 will cause the unit to abruptly slow down the moment it gets its feet wet.  If you're not using {{taglink|minHeight|0}}, you'll have to adjust this value accordingly to get a smooth application of the depthMod divider.
}}
}}


Line 186: Line 235:
{{new|86.0}}
{{new|86.0}}


These previously hard-coded variables allow control over how the pathfinder (default only, not QTPFS, see [[Modrules.lua]]) calculates costs for squares containing mobile units, if <code>avoidMobilesOnPath = true</code>.
These previously hard-coded variables allow control over how the pathfinder (default only, not [[QTPFS]], see [[Modrules.lua]]) calculates the cost for a '''MoveClass''' for squares containing mobile units, if and only if {{taglink|avoidMobilesOnPath|true}}.
 
{{tag
{{tag
|name = mobileBusyMult
|name = mobileBusyMult
Line 219: Line 269:


--kloot, Thu Jul 31, 2008
--kloot, Thu Jul 31, 2008
==Code to check your movdefs==
{{forumlink|topic=24866|title=A resource to check movedefs}} that game developers have used for years and find it quite useful.


==Example==
==Example==
===External Examples===
===External Examples===
[http://imolarpg.dyndns.org/trac/balatest/browser/trunk/gamedata/movedefs.lua 'Balanced Annihilation' movedefs.lua]
[http://imolarpg.dyndns.org/trac/balatest/browser/trunk/gamedata/movedefs.lua 'Balanced Annihilation' movedefs.lua]
[http://trac.caspring.org/browser/trunk/mods/ca/gamedata/movedefs.lua 'Complete Annihilation' movedefs.lua]


[http://spring1944.svn.sourceforge.net/viewvc/spring1944/trunk/S44Main.sdd/gamedata/movedefs.lua?&view=markup 'Spring: 1944' movedefs.lua]
[http://spring1944.svn.sourceforge.net/viewvc/spring1944/trunk/S44Main.sdd/gamedata/movedefs.lua?&view=markup 'Spring: 1944' movedefs.lua]
Line 231: Line 282:


[http://code.google.com/p/zero-k/source/browse/trunk/mods/zk/gamedata/movedefs.lua 'ZeroK' movedefs.lua]
[http://code.google.com/p/zero-k/source/browse/trunk/mods/zk/gamedata/movedefs.lua 'ZeroK' movedefs.lua]
[[Category: Unit_development]]
 
[[Category:Gamedata]]
[[Category:Gamedata]]

Latest revision as of 20:51, 6 July 2022

Movedefs.lua

Location

movedefs.lua is a file in the Gamedata/ directory of a Spring Game.

Purpose

This file defines MoveClasses which are used to determine pathing for units.

Source

The engine source code which parses the data from this file is viewable here:

Data Types

int
An integer number. eg. 5
float
A number with decimals. eg 1.023
bool
A value which can be true or false. eg true
string
Text, or more precisely a string of alphanumeric characters. eg "string of characters"
rgb
Three float components, representing red, green and blue components, ranged from 0.0 to 1.0. eg {0.0, 0.0, 0.0}
float3
Three float components, eg {0.0, 0.0, 0.0}
float4
Four float components, eg {0.0, 0.0, 0.0, 0.0}

Details

A mobile unit is assigned a MoveClass using the movementClass tag. The engine determines the unit's pathfinding based on the properties of the MoveClass, so analogous properties (e.g. footprintX) in the UnitDef should be the same for optimal behaviour.

All MoveClasses must belong to one of four possible types. A MoveClass is assigned a type simply by including it within the name string e.g. Tank_MyMoveClassName. Types are used in TypeMaps of Spring maps, which allow mappers to set per-type speed multipliers.

Types

  • Bot - A ground based MoveClass. The default type if no matching type string is found.
  • Tank - A ground based MoveClass. Identical to Bot other than interaction with TypeMaps.
  • Ship or Boat - Are synonyms. All ships / boat MoveClasses must belong to this type to behave as ships.
  • Hover - All hovercraft MoveClasses (traverse any depth of water without speed reduction) must belong to this class.

MoveClass Tags

string name  default: "" 

The name of the MoveClass. Usually passed by the sub-table variable name rather than using this tag (See #Example). Prior to 9.50 this had to contain "tank", "hover", "ship" or "boat" respectively for non-Bot types. This is now set using speedModClass.

int speedModClass  default: 1 New in version 95.0

Determines the speed modifier class used (See Mapdev:terraintype). Accepted values are 0 = Tank, 1 = KBot, 2 = Hover, 3 = Ship.

int footprintX  default: 1 

How wide the MoveClass is in footprint units, left to right. 1 footprint unit = 16 elmos. Cannot be below 1. For mobile units this should be the same as the footprintX of its UnitDef.

int footprintZ  default: footprintX 

How wide the MoveClass is in footprint units, top to bottom. 1 footprint unit = 16 elmos. Cannot be below 1. For mobile units this should be the same as the footprintZ of its UnitDef.

float crushStrength  default: 10.0 

Power of a unit with this MoveClass to crush features and units. Any features with a crushResistance less than this value will be crushed on contact. Any units with crushing enabled via Spring.SetUnitBlocking), in an impact where collider impulse exceeds collidee impulse and whose crushResistance is less than this value will also be crushed.

float maxSlope  default: 60.0 (15.0 for hover types) 

The maximum steepness of slope a unit with this MoveClass can climb in degrees. For further details see #How_slope_is_determined.

float slopeMod  default: 4.0 / (maxSlope + 0.001) 

How much a slope will slow a unit, 0 means no slowdown.

bool avoidMobilesOnPath  default: true 

Do the units attempt to avoid other mobile units when pathing?
  • Pro: groups moving without a ctrl-order clump much less
  • Contra: groups moving with a ctrl-order are less organized

bool allowTerrainCollisions  default: true New in version 96.0

Disable this to improve handling of large (>4 x 4) footprint units (See #4217 ).

bool allowRawMovement  default: false New in version 104.0

Enables native "raw move" (straight-line path) support (See also Spring.SetUnitMoveGoal and #4412 ).

Heat Tags

These tags are used in unit avoidance.

bool heatMapping  default: false 

This enables/disables generation and usage of path heats.

float heatMod  default: 0.0042 

The pathfinder cost modifier that is multiplied by the heat of the current square.

int heatProduced  default: 30 

How much heat to place on a square if a path goes through it. heat set = max(currentSquareHeat, heatProduced).

Flow Field Tags

These tags are used in unit avoidance.

bool flowMapping  default: true 

This enables/disables flow field mapping.

float flowMod  default: 1.0 

Multiplied by the objects mass for the y-component (up) of the flow vector. No idea what effect this has.

Tank & Bot-Only Tags

float depthMod  default: 0.1 

How much water will slow amphibious units. The deeper the water, the slower the movement.Replaced with a subtable in Spring 86.x

float maxWaterDepth  default: 0.0 

The maximum depth of water in elmos the unit can wade through.

Ship-Only Tags

float minWaterDepth  default: 10.0 

The minimum depth of water in elmos the ship requires to float in.

bool subMarine  default: false 

Is the ship a submarine; can it move underneath other ships?

Sub Tables

depthModParams

Only read for Bot and Tank MoveClasses, the depthModParams group contains several sub-tags. Depthmod is a system for changing the speed of units depending on how deep they are underwater.

      new formula is given by
        if h < depthModParams.minHeight: 1.0
        if h > depthModParams.maxHeight: 0.0
        else:
          depthScale = MAX(0.01, MIN(depthModParams.maxScale, (a * h * h) + (b * h) + c))
          depthMod = 1 / depthScale
      where
        h = unit's absolute height below water surface
        a = depthModParams.quadraticCoeff
        b = depthModParams.linearCoeff
        c = depthModParams.constantCoeff

float minHeight  default: 0.0 

The minimum depth where the depthMod curve applies. If the unit is shallower than the minHeight, no change in speed occurs.

float maxHeight  default: MAX_FLOAT 

The maximum depth where the depthMod curve applies. If the unit is deeper than the maxHeight, the unit is immobilized.

The following tags control the behavior of the unit within the active portion of the curve (depth is greater than minHeight but less than maxHeight). It would be best to simply open up your graphing program of choice and use the provided formula, but if you're scared of graphs you should read the descriptions below:

float maxScale  default: MAX_FLOAT 

This is the cap on how severe the depth effect can be. For example, lets say that you use a maxScale value of 2. If a unit is at the depth where its scale reaches the max (usually near its maximum depth; with a maxScale value of 2), the slowest it will go is half of its maximum speed. In other words, (maxVelocity / maxScale). Therefore, as another example, a value of 4 would cause the unit's maximum speed (near the units maximum depth) to be 25% of it's maxVelocity.

float quadraticCoeff  default: 0.0 

The application of the speed-divider effect is modelled as a quadratic. This is the "depth-squared" component of that. That is, a value set here will be applied exponentially as the unit gets deeper, therefore it is best to use very small numbers for this tag.

float linearCoeff  default: depthMod 

The application of the speed-divider effect is modelled as a quadratic. This component makes divisor increase linearly with the depth of the unit. So with a value of 0.1, for example, a unit would go from 1/2 speed to 1/3 speed and 1/3 speed to 1/4 speed each time it goes 10 units deeper.

float constantCoeff  default: 1.0 

The application of the speed-divider effect is modelled as a quadratic. This is the constant component of the divisor. If you want a gradual decrease of speed and your minHeight = 0 (the waterline) then this value must be 1. Using less than 1 will cause the unit to go faster as it hits the water, and using greater than 1 will cause the unit to abruptly slow down the moment it gets its feet wet. If you're not using minHeight = 0, you'll have to adjust this value accordingly to get a smooth application of the depthMod divider.

speedModMults

New in version 86.0

These previously hard-coded variables allow control over how the pathfinder (default only, not QTPFS, see Modrules.lua) calculates the cost for a MoveClass for squares containing mobile units, if and only if avoidMobilesOnPath = true.

float mobileBusyMult  default: 0.1 

The cost multiplier for mobile units which are 'Busy'; Not currently being built and with a non-empty command queue, but not moving on a path. Clamped to values above 0.01.

float mobileIdleMult  default: 0.35 

The cost multiplier for mobile units which are 'Idle'; Either currently being built or with an empty command queue. Clamped to values above 0.01.

float mobileMoveMult  default: 0.65 

The cost multiplier for mobile units which are 'Moving'; Trying to follow their own path. Clamped to values above 0.01.

How slope is determined

Spring doesn't represent terrain slopes in degrees, internally it uses (1.0 - the terrain normal's y-component) so the slope of vertical faces is 1 and that of horizontal ones 0. A unit's maxSlope value (which is in degrees in its movedef) is converted so that the "can we go here?" (ie "maxSlope > terrainSlope?") comparisons are meaningful, the formula is 1.0 - cos(DEG2RAD(maxSlope * 1.5)). If you want to know the terrain angle in degrees, compute RAD2DEG(arccos(1.0 - terrainSlope)). For a bot with a maxSlope of 36 degrees (~0.41221 in "Spring format"), the maximum tolerable terrain angle is approximately

RAD2DEG(arccos(1.0 - 0.41221))

or 54 degrees. If maxSlope was 30, the MTTA would be 45, and if it was 60 (the highest sensible value due to that 1.5 scalar and the absence of overhanging cliffs) the bot could mount any terrain. In other words you do not need the long mathematical derivation, just remember that maxTerrainAngle = maxSlope * 1.5

--kloot, Thu Jul 31, 2008

Code to check your movdefs

A resource to check movedefs that game developers have used for years and find it quite useful.

Example

External Examples

'Balanced Annihilation' movedefs.lua

'Spring: 1944' movedefs.lua

'Spring Tutorial Game' movedefs.lua

'ZeroK' movedefs.lua