# Bos Wars: Magic

Stratagus FAQ PREV NEXT LUA Index

DefineMissileType DefineSpell

## Intro - Introduction to spells and missiles.

This containts everything around spells and missiles. Though it might not be obvious at start missiles are also suited for complex behaviour and included here.

## Functions

### DefineMissileType( "missile-name", { tag = value, ...} )

This is the function to define a missile type.

missile-name
  This is the unique identifier of the missile.

Possible tags:

File = "file-path"
  This is followed by the path of the file with the missile graphics.
Size = {x, y}
  This if followed by a list of X and Y sizes of the missile sprite. F.E. 'size '(32 32)
Frames = number
  This is the number of frames in the file. Missiles lack complicated animation scripts and just have a bunch of frames with equal duration.
NumDirections = number
  The number of directions in the file for the missile. Should be 8 (or 5 for flipped missiles).
DrawLevel = Number
  The draw level of the missile. Missiles and units are sorted by this value to determine the draw order.
FiredSound = "Sound-file"
  Name of the sound played when the missile is fired.
ImpactSound = "Sound-file"
  Name of the sound played when the missile hits it's target.
Class = "class-type"
  Various missiles can have wierd behaviours. This tag is followed by an identifier that specifies some of that behaviour. Here is a list of currently supported missile classes:
  "missile-class-none"
    Missile does nothing. Shouldn't really be used.
  "missile-class-point-to-point"
    Missile flies straight to destination animating on the way
  "missile-class-point-to-point-with-hit"
    Missile flies straight to destination keeping the first frame and the finishes the animation when hitting
  "missile-class-point-to-point-cycle-once"
    Missile flies straight to destination and animates ONCE from first to last and back again. To be used for catapult and the like to make a projectile bigger mid-way to the target
  "missile-class-point-to-point-bounce"
    Missile flies straight to destination, and the "bounces" by hitting every other tile on the path onward. This will also add one aditional flag:
    num-bounces
      This if folowed by an integer, representing the number of bounces(hits)
  "missile-class-stay"
    Missile will just go through it's animation once and vanish. booooring.
  "missile-class-cycle-once"
    Missile will just go through it's animation from start to and and back again, then vanish.
  "missile-class-fire"
    Missile is used for fire. More documentation?
  "missile-class-parabolic"
    Missile flies to destination with a parabolic path. It used the same animation as cycle-once
  "missile-class-land-mine"
    Missile is a landmine, it will sit quietly and wait for someone to step on it. You can use time-to-live as a timeout.FIXME more configurable
  "missile-class-whirlwind"
    Missile for the whirlwind effect FIXME more configurable
  "missile-class-flame-shield"
    Missile rotates around target unit and damages everything it touches FIXME more configurable
  "missile-class-death-coil"
    Missile is death coil, will drain health from target or enemy units in the area and feed it to the caster.FIXME more configurable
Delay = number
  Delay in game cycles after the missile generation, until the missile animation and effects starts. Delay denotes the number of display cycles to skip before drawing the first sprite frame and only happens once at start.
Sleep = number
  This are the number of game cycles to wait for the next animation or the sleeping between the animation steps. All animations steps use the same delay. 0 is the fastest and 255 the slowest animation. Perhaps we should later we will use animation scripts for more complex animations.
Speed = number
  The speed how fast the missile moves. 0 the missile didn't move, 1 is the slowest speed and 32 s the fastest supported speed. This is how many pixels the missiles moves with each animation step. The real use of this member depends on the missile class. This is currently only used by the point-to-point missiles.
Range = number
  Determines the range in which a projectile will deal its damage. A range of 0 will mean that the damage will be limited to the targetted unit only. So if you shot a missile at a unit, it would only damage that unit. A value of 1 only affects the field where the missile hits. A value of 2 would mean that the damage for that particular missile would be dealt for a range of 1 around the impact spot. All fields that aren't the center get only 1/SpashFactor of the damage. Fields 2 away get 1/(SplashFactor*2), and following...
SplashFactor = number
  The Splash divisor for damage done with range
ImpactMissile = "missile-type"
  You can use this to spawn another missile on impact. F.E. ImpactMissile = "missile-explosion"
SmokeMissile = "missile-type"
  The name of the next (other) missile to generate a trailing smoke. So it can be used to generate a chain of missiles.
CanHitOwner = boolean
  Determines if the missile will affect the caster or not.
FriendlyFire = boolean
  Determines if the missile will damage units belonging to the same player of the caster or to an ally.

#### Example

    DefineMissileType("missile-fireball",
      { File = "missiles/fireball.png", Size = {32, 32}, Frames = 5, NumDirections = 5,
      ImpactSound = "fireball hit",
      DrawLevel = 50, Class = "missile-class-point-to-point-bounce", NumBounces = 5,
      Sleep = 1, Speed = 16, Range = 1,
      ImpactMissile = "missile-explosion" } )

### DefineSpell( "spell-ident", tag, value, ... )

This is the function to define a spell, including it's effects and targetting conditions. Be very carefull, defining random flags will probably make the game crash.

"showname", "name"
  A neatly formatted string to be shown by the engine on the screen.
"manacost", number
  The mana cost of the spell. But some actions (AdjustVitals, Summon, Polymorph) use it for their own mana calculation and so. If spell use at least of these actions, mana is computed by these action (which use manacost also),else it was substract from caster mana.
"repeat-cast"
  If specified, the caster will cast it again. To be used with spells like area-bombardment to cast it again (area-bombardment is stackable)
"range", number or "infinite"
  The casting range of the spell, do not confuse this with area effect range. It's normally an integer value, but you can specify a special value "infinite" to let the spell be casted on the entire map.
"target", "self" or "position" or "unit"
  Target type information. The following values are acceptable:
  - "self": The spell will only affect the caster or the area around him, no targetting at all.
  - "position": The unit will target a position.
  - "unit": The unit will target an unit. The spell will be aborted if the target dies.
  You can still use position spells on units, it will target the unit's position. If the unit dies however the caster will stop. (Some spells get casted until there is no more mana left).
"conditions", {flag, value, ...}
  This is the condition for being able to cast the spell. Think of it as a function that takes an unit as a parameter and return either yes or no depending on the unit properties. Here is how a condition looks like:

      "condition", {
        "building", "false"
        "max-slow-ticks", 10}

  Here are the supported parameters:
  "alliance", "true" or "false" or "only"
    This is one of the bool parameters (can't think of a better name). It is followed by "true", "false" or "only". Imagine this as a question, is the target in alliance? The answer is yes/no. A "true" parameter makes it always pass(and it's the default.), "false" parameter passes when the answer is NO, and "only" passes only when the answer is yes.
    It doesn't really makes sense to ever say true, since you might just as well ommit it. "alliance false" means the spell won't work on allied units. "alliance only" will make a spell that works only on allied units (can't think of any though). Your own units are considered allied too.
  "opponent", "true" or "false" or "only"
    This is a bool parameter too, just like alliance. I specifies the behaviour for opponent units. Neutral units are neither allied unit nor opponent units.
  "self", "true" or "false" or "only"
    This is a bool parameter too, just like alliance. I it a bit more special, since it specifies the behaviour for casting on yourself. A LOT of spells specify "self false", to disallow casting on yourself.
  bool-flags, "true" or "false" or "only"
    There is no parameter called bool-flags. You can however use flags defined by DefineBoolFlags() just like a bool parameter. For instance "organic", "only" will make a spell work only on units marked with the "organic" flag.
  variable, {flag = value}
    There is no parameter called variable. You can however use variables defined by DefineVariables()
    Enable = "true" or "false" or "only"
      variable is enable ?
    MinValue = number
      minimal value allowed.
    MaxValue = number
      maximal value allowed.
    MinMax = number
      minimal maximum-value (the field Max of the variable) allowed.
    MinValuePercent = number
      minimal value allowed in percent with Max value.
    MaxValuePercent = number
      maximal value allowed in percent with Max value.
    ConditionApplyOnCaster = boolean
      if true, check caster instead of target.
"autocast", {flag, value}
  Autocast works very closely with conditions. It functions by selecting every unit in range and trying to check of they fit the condition. If they do, the spell is casted. Of course, this is a very primitive mechanism, but it works for simple spells like heal. As you might have noticed, some of the finer restrictions in conditions are designed for autocast (like not casting buffs on cowards). Autocasting position target spells is not supported, sorry. Here is a formal list of parameters:
  "range", number
    The range in which autocast runs. I think it's square?
  "combat", "only" or "true" or "false"
    This is a bool parameter, like in condition. It's autocast-specific and NOT part of conditions due to technical considerations. Combat is not unit-specific, it only depends on caster location. combat mode is when there are non-coward enemy units in range. most offensive spells obviousely only should be used in combat. (can you say offensive buffs?)
  "condition", {flag, value}
    This is followed by a list exactly like in "condition". As it was said before, this is evaluated for each and every unit in range, and if a unit passes, the spell gets casted.
"ai-cast", {flag, value}
  This is identical to autocast in syntax. It's used by the AI (computer controller player) rather then by a human players units. In general this should be a little better than autocast (and make human players think some more). There no reason to repeat the syntax of autocast here.
"action", {{"operation-name", flag, value, ...} , ...}
  The effect of the spells. You can add multiple actions. Here are the supported operations, their paramenters, and what they do.
  "area-bombardment"
    This will a number of missiles to be thrown in a square area. Here are the available tags:
    "fields", number
      The size of the affected square. This will get centered on the target It should really be an odd number, or it will look wierd (not centered.)
    "shards", number
      The amount of missiles to throw at random in the square.
    "damage", number
      The damage of each individual missile.
    "start-offset-x", number
    "start-offset-y", number
      A missile hitting x,y will start at x + start-offset-x, y + start-offset-y. This value is in pixels, for better precision.
  "adjust-variable", {VariableName = {tag = value, ...} or number, ...}
    This will adjust variable "VariableName" of the unit (defined by DefineVariables().)
    Using number n is equivalent to {Value = n, Max = n, Enable = (n == 0)}
    Enable = boolean
      Set Enable value.
    Value = number
      Set Value value.
    Max = number
      Set Max value.
    Increase = number
      Set Increase value.
    InvertEnable = boolean
      Invert Enable value.
    AddValue = number
      Add to Value value.
    AddMax = number
      Add to Max value.
    AddIncrease = number
      Add to Increase value.
    IncreaseTime = number
      add number time Increase to the value.
    TargetIsCaster = "target" or "caster"
      Apply to target or caster.
  "adjust-vitals", tag, ...
    This will adjust vitals of the unit. Vitals are health, mana, and on a sunny day maybe even shield. mana of caster is modified like this : newmana = oldmana - manacost * castcount. Where castcount is the number of time vitals are inc/decreased. Possible tags:
    "hit-points", number
      Unit hit-point gain, or loss if negative.
    "mana", number
      Unit mana gain, or loss if negative.
    "max-multi-cast", number
      This spell usually has some very small limits (like heal 2 hit-points for 1 caster mana), and will get casted multiple times at once, until the hp/mana limit for the unit is reached. You can set this to a reasonable value so the spell can only get casted so many times at once. Like heal 2 hit-points for 1 caster mana up to 20 hit-points/10 mana per cast
  "demolish", tag, ...
    This will remove any trees/rocks/walls in and inflict a fixed damage to a fixed area. Possible tags:
    "damage", number
      Each and every unit in range will receive that damage. FIXME: no support for dampening damage.
    "range", number
      The range of the terrain and unit damage.
  "summon", tag, ...
    This will summon a new unit. Manacost is substracted if action success (failed when no corpse or no place). Possible tags:
    "unit-type", "unit-type-name"
      Type of the unit to summon. Must be already defined.
    "ttl", number
      Time to live. The unit will only survive for that time, afterward it will receive 1 damage every game cycle, ending it's life. If this is 0 or ommited then the summoned unit is permanent
    "require-corpse"
      This flag does not take a value. When specified, the caster will summon an unit from a corpse, and consume the corpse in the process. You should make sure the summoned unit dies without a corpse.
    How to do a reveal-map spell: define a special unit, give it the revealer flag, and set the spell's range to "infinite". Please see DefineUnitType()
  "polymorph", tag, ...
    This will tranform the unit, giving it a new unit type. Before you ask, temporary polymorphing is not supported, but it would be a nice feature to add in the future. Mana is substracted if action sucess (fail if no place for the new unit) There is only one tag:
    "new-form", "unit-type-name"
      Type of the unit to transform to. Must be already defined. This spell can be used as an instant-kill spell by polymorphing into a harmless unit, like a chicken.
  "spawn-missile", tag, ...
    This will spawn a missile in the game. It's one of the most versatile spell variants. Here are the paramenters:
    "ttl", number
      Time to live for the missile. Usually means that the missile is gone after this time, but for some missile classes it means something else.
    "damage", number
      This is the damage for this missile, overriding the standard damage defined for the missile.
    "delay", number
      This is the delay for the missile. it means the missile will only appear after this many ticks.
    "start-point", {flag, value, ...}
    "end-point", {flag, value, ...}
      Point to point-ish missiles need a start and an end point for the trajectory.
      "base", "caster" or "target"
        The base for the location calculation. Can be either caster or target.
      "add-x", number
      "add-y", number
        How much to add to the x or y coordinate, in pixels
      "add-rand-x", number
      "add-rand-y", number
        Add a random from 0 to number to the x or y coordinate, in pixels
  "capture", tag, ...
    This will convert the target unit to the casters side. Very useful for capturing enemy buildings and controling enemy units. None of these tags need to be specified.
    "damage", number
      The amount of damage the unit takes before it is converted. Usually used with percent below
    "percent", number
      The precent of the target's total HP it has to be reduced below before it will be converted.
    "sacrifice"
      If this tag is given the caster will die after casting the spell.
"depend-upgrade", "upgrade-name"
  The dependency of the spell. Spell is available only once the upgrade is searched. Upgrade must be already declare.

#### Example

    DefineSpell("spell-healing",
    	"showname", "Healing",
    	"manacost", 6,
    	"range", 6,
    	"target", "unit",
    	"action", {{"adjust-vitals", "hit-points", 1},
    		{"spawn-missile", "missile", "missile-heal-effect",
    			"start-point", {"base", "target"}}},
    	"condition", {
    		"organic", "only",  -- it is a defined-flag
    		"Building", "false",
    		"HitPoints", {MaxValuePercent = 100}
    	},
    	"depend-upgrade", "upgrade-healing",
    	"sound-when-cast", "healing",
    	"autocast", {"range", 6, "condition", {"alliance", "only", "HitPoints", {MaxValuePercent = 90}}}
    )

Last changed: $Id: magic.html 8569 2007-02-10 23:21:43Z feb $
All trademarks and copyrights on this page are owned by their respective owners.