M25’s AI Extensions

 

Version 2.3

 

This document is intended for modders who are at least familiar with the Freedom Force editor and how to set up characters within the editor.

Note: most of this documentation is obsolete, as it applies to FFX 2.3.

 

 

M25’s AI Extensions. 1

Building an AI:  Quickstart 1

Step 1: Setting up the character in the editor 1

Step 2: Extending the AI 2

Step 3:  Using the AI 3

More on Triggers. 3

Danger 4

Remedy. 4

M25_AI_ONLY.. 4

Subtype. 5

Timer 5

More on Tactics. 6

Format 6

The Order of Tactics in a List 6

Tactics have a ‘Percent to Use’ Parameter 7

Parameters. 7

Standard Priorities. 8

Subtypes and Situations. 8

List of Tactics. 10

FFX Tactics. 16

Hybrid Characters: Which Game AI to Use?. 20

Building a Completely New, Scripted AI 20

Examples. 21

 

 

Building an AI:  Quickstart

 

NOTE:  You must have FFX 2.3 installed for the AI to work.

 

Step 1: Setting up the character in the editor

 

Here’s a simple example from the Fantastic Force mod - Juggernaut.  I don’t always build a complete AI within my scripts, but instead add to an existing AI.  So here, I would define Juggernaut and his powers in the editor and assign him one of the existing AI’s (in the mod he uses Mr. Mechanical’s AI). 

 

Even better, you can now create a .hero file and use Alex’s Hero Editor to import it directly into the game without having to use the editor. 

 

Step 2: Extending the AI

 

Now, the AI you choose will usually not do everything you want it to do, so you can define an extension to the AI.  The Mr. Mechanical game AI will stomp around nicely, use a melee attack and use a ranged attack to shoot down flyers.  However, I’d like Juggernaut to have an area attack, another melee attack and a shockwave ranged attack he can use against those who try to run!   Finally, I want to give him the feeling of being unstoppable by allowing him to regenerate his health. 

 

You define your  additional AI by adding an entry to the AIExtensions list in the file called m25newaidata2.py.

 

['juggernaut',

     ['timer',3,

          "TAreaAttack('juggernaut foot',situation=’swarmed’)",

          "TMeleeAttack('juggernaut slam')",

          "TRangedAttack('juggernaut shockwave',energy=35)",

     ],

],

 

Each entry is itself a list and has a specific format.  Since this is essentially python code, you should follow it rigorously.

 

Name:

As you can see, the first string is the name of the character.  Actually it is the name of the TEMPLATE for that character.  Every character with this template will be given this AI.

 

Triggers:

After the name are a number of sub-lists that start with a string (the trigger) and a number and/or a list of tactics.  The trigger is an event in the game that prods the AI into doing something.

 

Juggernaut uses a single trigger.  It’s called ‘timer’.  It does what you might think it does – try to do something every X number of seconds.  3 is the number of seconds – so Juggernaut will try to apply any of the tactics in this list every 3 seconds.

 

Tactics:

Tactics are the actual actions that the AI should perform. The tactics are named so that they should be fairly self-explanatory (but there is a complete list of what they are and what they do in another section).

 

Each tactic basically consists of a response to a situation.  For example: ‘if I am surrounded by enemies then I should try an area attack.  Or, ‘if I have a stasis attack and my enemy is not in stasis, then try the stasis attack on them.’

 

The order of the tactics is important.  The tactics are tried in the order they appear. 

 

In the example:

  • Juggernaut will first try to use an area attack called ‘juggernaut foot’ if there is a group of enemies around him (that is he is in the situation of being swarmed by enemies). 
  • Second, he will try a melee attack called ‘juggernaut slam’ if there is an enemy in melee range. 
  • Third, he will try a ranged attack called ‘juggernaut shockwave’ if there is an enemy in range and he has enough energy (35 energy points).

 

Step 3:  Using the AI

 

If you are just creating a new AI for the Danger Room, simply:

 

  1. Open up Data/Mission/Scripts/m25newaidata2.py
  2. Add your new AI inside the AIExtensions list.

 

 

Using the AI in a mod is a little more complex, but still easy.

 

  1. Make sure you have FFX 2.3 or higher installed (the people who play your mod will also have to have FFX installed).
  2. Copy the Data/Missions/Scripts/m25newaidata2.py to your mod/Missions/Scripts directory.  Rename it m25newaidata2S.py. 
  3. Define your AI and add it to the AIExtensions list in m25newaidata2S.py
  4. Go into ffxextrasS.py and make sure that FFX_RULES_CAMPAIGN_M25AI is set to 1 (it defaults to 0).
  5. IMPORTANT!!!!!  Import m252.py into your mission (use “from m252 import *”).  Make sure m252.py is the ONLY thing you import into your mission script.  It automatically imports other files such as cshelper and ffx so no need to import them separately.
  6. Call SetMission(x), where x is some number, somewhere within the mission, usually within OnPostInit() to start up the AI and FFX.
  7. If you spawn new characters AFTER you call SetMission(x)  then you should call  NextStage() to initialize the AI for these newly spawned characters.

 

 

That’s it.  You’re ready to go.

 

 

More on Triggers

 

A trigger is an event that causes the AI to evaluate a set of tactics.  There are several triggers currently defined.

 

Danger

 

Occurs when the character detects danger.  Danger is defined in the game as the character detecting hostile power use or taking damage.  Danger takes a list of tactcs.

 

Example:

['danger',

          "TActiveDefenseRandFly('human_torch Fire Shield',energy=25)",

],

 

When danger is detected, try the active defense with random fly tactic.

 

Notes:

  • Danger is triggered a lot in the game, so set the percentage fairly low on the tactics you use, otherwise they will be triggered constantly.

 

 

Timer

 

Occurs every X seconds, where X is a number you define.

 

Example:

['timer',3,

          "TAreaStasis('mr_fantastic Elastic Coils',energy=50)",

],

 

Try to use the elastic coils power to stasis a group of enemies every 3 seconds.

 

You can also use the keyword ‘auto’ instead of a number (make sure you put ‘auto’ in quotes).  Auto means: run these tactics whenever I’m sitting idle and waiting for something to do.  That way you don’t have to fiddle with numbers for the timer AND it saves a lot of processing power so the AI runs faster.  Its win-win all over isn’t it?

 

IMPORTANT:  The ‘auto’ keyword should ONLY be used when you are building a complete custom AI.  If you’re building a hybrid AI, then use a number.  If you don’t know what the difference is yet (don’t worry, look at some examples and you will), then use a number and not ‘auto’.

 

Example:  the basic custom AI looks like this.

[‘timer’, ‘auto’,

            some tactics

],

 

 

Additional AI Sections

 

M25_AI_ONLY

 

This is a special trigger that tells the game to only use the tactics you have defined for this character.  In other words, when you use this trigger, you must put together a complete custom AI for the character.

 

NOTE:  if you want a custom AI, it is better to use the ‘auto’ feature of the Timer trigger instead of M25_AI_ONLY.  You will get much better results.

 

Subtype

 

Within the subtype section you can define any special conditions that apply to a character.

 

For example, ‘thug_with_bat’ is the standard bat wielding thug that everyone loves to pound on.  There are a couple of special things about him that we’d like to specify in the AI: first, he has a weakness to mental attacks and, second, he is primarily a close combat (melee) character.

 

His subtype section looks like this:

 

['subtype',

          "weakness_mental",

          "melee",

],

 

The subtype section is intended to give the AI more information so that it can make better decisions.  So if another AI (say El Diablo) is squaring off against this thug, I can give El Diablo’s AI a tactic which says if I’m facing a melee character, then fly up into the air.

 

That tactic would look like this:

 

TAirSuperiority(subtype=’melee’)”,

 

There are a lot of built-in subtypes.  See the section on Standard Subtype and Situations.   You DON’T have to put most of them into the subtype section.  The AI will calculate them automatically. The subtype section is instead meant for special conditions that you want to add yourself (something that is important to mod-makers).

 

 

Target

 

By default, the AI will target the closest enemy and start blasting.  Sometimes, though, you want a little more control over what the AI attacks, and in those cases you can use the Target section.

 

For example, if I want Nuclear Winter to target enemies that are not frozen or blanked I would set up his target section like this:

 

[‘nuclear winter’,

            [‘target’,

                        TargetSubtype(subtype=[’not frozen’,’not blanked’])”,

            ],

],

 

More on Tactics

 

Tactics are the actions that you can assign to an AI.  Each tactic basically consists of a response to a situation.  For example: ‘if I am surrounded by enemies then I should try an area attack.  Or, ‘if I have a stasis attack and my enemy is not in stasis, then try the stasis attack on them.’

 

Format

 

Each tactic is written up to look like a call to a python function (because it is).  However, each tactic must have quotes around it and should end with a comma. 

 

"TMeleeAttack('mr_fantastic All Around',energy=25)",

 

The Order of Tactics in a List

 

Order is VERY important.  When a trigger occurs, it tries out its list of tactics in the order that they appear.   It’s like a giant if… then  statement. 

 

This example is from Mr. Fantastic

 

     ['timer',3,

          "TAreaStasis('mr_fantastic Elastic Coils',energy=50)",

          "TRangedPowerNull('mr_fantastic Nullifier',energy=50)",

          "TMeleeAttack('mr_fantastic All Around',energy=25)",

     ],

 

It can be read like so:

 

If there are any enemies around me, try to stasis them with elastic coils.

Otherwise, if my enemy isn’t already nullified, try a power null on them.

Otherwise, if there’s a target in range, try a melee attack.

 

Tactics have a ‘Percent to Use’ Parameter

 

In order to randomize the AI and produce a more fluid experience, each tactic has a percentage assigned to it.  When trying a tactic, the AI generates a random number and if the number is less than the percentage to use the tactic, it is then evaluated.

 

Why do it this way?  If I didn’t, then the AI would feel very scripted and predictable.

 

Each tactic has a default percentage assigned to it but you can change it easily by supplying a pct=XX parameter.

 

Parameters

 

Each tactic has a fairly long list of parameters that you can use to fine-tune the use of the tactic.  Most of them have a default value that works well in most situations.

 

Definitions of common parameters:

 

  • Power:  the name of the power to use.  The power must be defined within the editor or you will get an error.  This is the only parameter that doesn’t have a default value.
  • Pct:  the percentage chance to use the tactic.
  • Time: the amount of time the tactic takes to use in seconds.
  • Energy: the amount of energy required to use this tactic.  The energy will be deducted from the character if the tactic is used.  If you set it too low, the character will get stunned a lot.
  • Mindist: the minimum distance away an enemy must be before the character will use this tactic.
  • Maxdist: the minimum distance away an enemy can be before the character will use this tactic.
  • Type: who to use the tactic on.  There are two choices: ‘enemy’ for enemies and ‘friend’ for allies.
  • Subtype: any other conditions the target must meet.  For example, you can set the subtype to ‘metal’ so that a tactic is only used on enemies that are made of metal.
  • Radius: the radius of explosive ranged powers.  Used to prevent a character or his allies from being hit by friendly fire.
  • Situation: any conditions that apply to the character using the tactic.  For example, setting the situation to swarmed means that the tactic will only be used if the character is surrounded by two or more enemies.
  • Priority: using higher numbers here means that the tactic has a higher priority.  A high priority tactic can interrupt a low priority one.  For example, when a bunch of thugs start shooting at Mentor, he should raise his shields instead of trying to pound the nearest thug with a psychic-slash.  The defense tactic to raise his shields has a higher priority.
  • Role: an additional parameter that you can specify to decide when to use a tactic.  For example you might assign the role of ‘healer’ to a character when in a group, or ‘combat’ when not in a group and have tactics that are appropriate to each of those roles.

 

All of these, except for power, are named parameters.  To make sure you are compatible with future versions of the AI scripts, you should use the format parameter=value when assigning them in a tactic.

 

Example:

"TRangedAttack('silver_surfer Cosmic Blast', pct=10, time=2, energy=35, mindist=10, maxdist=150, type='enemy', subtype=’not resistant_energy’)",

 

Use the ranged attack power ‘silver_surfer Cosmic Blast,’ 10 percent of the time.  The power takes 2 seconds to use and requires 35 energy.  It has a range of between 10 and 150.  It should be used on enemies who are not resistant to energy damage.

 

 

 

Standard Priorities

 

Usually you won’t need to specify the priority parameter of a tactic.  Just leave it out and everything will work fine.  However, if you do need to change it, here are the standard priorities that I use.

 

  • Priority 2:  all movement powers
  • Priority 5:  all combat powers
  • Priority 10: all defensive powers

 

 

Subtypes and Situations

 

Subtypes and situations are powerful techniques that let you customize when a tactic should be applied.  They are conditions on the target and user of the tactic that must be met before the tactic is applied.  For example, suppose we want Minute Man to run up to opponents so that he can bash them.  We’d use a tactic like:

 

TMoveTo()

 

This works nicely, but only if the target is on the ground.  If Minute Man’s target is flying, he’ll still run up to them, but then be unable to actually hit them, and kind of just stand there and look dumb.  So instead, we’ll apply a subtype to the tactic that says, only run up to the target if they aren’t flying.

 

TMoveTo(subtype=’not flying’)

 

If we want to specify that Minute Man shouldn’t chase after very fast opponents either, then we can use a list of subtypes like so:

 

TMoveTo(subtype=[‘not flying’,’not higherspeed 6’])

 

And we can add that if they are flying, use the Patriot Throw power to bring them back down to earth.

 

TRangedAttack(‘minute man Patriot Throw’, subtype=’flying’)

 

 

 

Subtypes and situations are actually opposite sides of the same coin.

 

A subtype is something that applies to the target of a tactic.

 

A situation is something that applies to the user of a tactic.

 

For example, you can specify to use a particular power only when flying (such as El Diablo’s Inferno attack).

 

TRangedExplosive(‘el diablo Inferno’,situation=’flying’)

 

 

 

There are quite a few standard subtypes built into the AI that you can use in your tactics (see the list below).   However, you can also define your own subtypes without having to write any code.  Suppose I wanted to say that the Supercollider is a tank.  Now, ‘tank’ is not a built-in subtype, but that doesn’t matter.  I can easily add my own.  I would use the subtype section within the Hulk’s Ai definition in order to define the Supercollider as a talk.

 

[supercollider’,

            [‘subtype’,

                        tank’,

            ],

],

 

Now I can use the ‘tank’ subtype in any of the tactics in any of the other AIs and they will know that Supercollider is a tank.

 

 

Built-in subtypes:

 

  • air – character is made of air
  • acid_burnt – character is taking acid damage
  • alone – character does not have any friendly characters nearby
  • blanked – character has been mind-blanked (has question marks above his/her head)
  • blind – character has been blinded
  • chargedup – character is under the influence of a chargeup power (like Minute Man’s 300 percenter)
  • civilian – character is a civilian
  • cloth – character is made of cloth
  • clustered – character has at least 2 friends nearby
  • concrete – character is made of concrete
  • density_maxed – characters is under the influence of a density max power
  • displaced – character has been displaced (ghost-like)
  • energy – character is made of energy
  • exiled – character has been exiled
  • enraged – character has gone berserk
  • fire – character is made of fire
  • flesh – character is made of flesh
  • flying – character is flying
  • frozen – characrer has been frozen (encased in ice)
  • hero – character is a hero
  • hexed – character has been hexed
  • higherenergy x – character has more energy than x
  • higherhealth x – character has more health than x
  • highermass x – character has more mass than x (heavier than)
  • higherspeed x – character is faster than x
  • higherstrength x – character is stronger than x
  • hurt – character has taken damage
  • hypnotized – character is hypnotized
  • ice – character is made of ice
  • invisible – character is invisible
  • irradiated – character is taking radiation damage
  • lowerenergy x – character has less energy than x
  • lowerhealth x – character has less health than x
  • lowermass x – character has less mass than x (is lighter than)
  • lowerspeed x – character is slower than x
  • lowerstrength x – character is weaker than x
  • metal – character is made of metal
  • nulled – character has been power-nulled
  • panicked – character is in the panic state
  • resistant_acid – character is resistant to acid
  • resistant_cold – character is resistant to cold
  • resistant_crushing – character is resistant to crushing damage
  • resistant_heat – character is resistant to heat and fire
  • resistant_piercing – character is resistant to piercing damage
  • rubber – character is made of rubber
  • staticked – character is under the stasis effect
  • stasis – character is under the stasis effect
  • stone – character is made of stone
  • stunned – character is stunned
  • swarmed – character is closely surrounded by 2 or more enemies
  • throwing – character is attempting to throw an object
  • weakened – character is nulled, frozen, stunned, blanked, panicked or hexed
  • wood – character is made of wood

 

 

List of Tactics

 

The following is a list of the tactics currently defined.  The numbers after the parameters are the default values for those parameters.

 

These don’t cover every possible situation, and more will be added in future versions.

 

 

Defensive Tactics

 

These are intended to be used with the ‘danger’ trigger.

 

TActiveDefense(power, pct=30, time=4, energy=0, situation='none', role='none', priority=10)

 

Use an active defense.  Nothing too special here.

 

 

TActiveDefenseRandMove(power, pct=30, time=4, energy=0, mindist=50, maxdist=150, situation='none', role='none', priority=10, movetype=’move’)

 

Use an active defense, and while that defense is in place, move to a random point at least mindist away and at most maxdist away (try to get away from further attacks).  If you want them to fly, use movetype=’fly’

 

 

TDangerSprint(power, pct=30, time=0.5, energy=0, mindist=30, maxdist=150, situation='none', role='none', priority=10)

 

Use the sprint power to get out of the way of an attack.  It works well for defense against projectile attacks, area attacks or multiple contact melee attacks.

 

 

TDefendAgainst(power, pct=30, time=4, energy=0, mindist=50, maxdist=500, type = 'enemy', subtype='none', situation='none', role='none', priority=10)

 

This is a special defensive tactic that is meant to be put in the ‘timer’ section of the AI.  Use a defensive power if the enemy being targeted fits the type and subtype.  For example, I use this to get Mentor to put up a defensive shield whenever another character is trying to throw a car at him.

 

 

 

Special Tactics

 

TEnergize(pct=30)

 

Regain a full amount of energy.

 

 

TSpecial(power, pct=20, time=5, energy=0)

 

Use some sort of power that doesn’t need a specific tactic. 

 

 

 

Movement Tactics

 

 

TAirSuperiority(pct=30, mindist=0, maxdist=300, type='enemy', subtype='none', situation='none', role='none', priority=2)

 

If an enemy is within maxdist, then hover in the air (get off of the ground).

 

 

TFleeMelee(pct=40,time=1,mindist=100,maxdist=400, subtype='none', situation='none', role='none', priority=5, movetype='move')

 

If an enemy gets within mindist, then try to move away to a point not further away than maxdist.  Use movetype to specify what type of movement to use.  In other words, if you want them to fly set movetype=’fly’

 

 

TLand(pct=30, time=0.5, mindist=100, maxdist=400, type='enemy', subtype='none', situation='none', role='none', priority=2)

 

If flying, land if an enemy is between mindist and maxdist away.

 

 

TMoveTo(pct=30,time=1,mindist=50,maxdist=300,type='enemy', subtype='none', situation='none', role='none', priority=2,movetype='move')

 

Move to someone between mindist and maxdist away.  The type sets who to move to, either a ‘friend’ or an ‘enemy’.  If you want them to fly, set movetype to ‘fly’

 

 

 

TMoveToThrowable(user,pct=30,time=1,mindist=100,maxdist=400,type='enemy', subtype='none', situation='none', role='none', priority=2, objdist=10000)

 

Move to an object within objdist that can be thrown.

 

 

TMoveToWithDefense(power, pct=30, time=1, energy=0, mindist=70, maxdist=300, type='enemy',subtype='none',situation='none', role='none', priority=5, movetype ='move')

 

Activate a defensive power and then ove to someone between mindist and maxdist away.

 

 

 

TRandMove (pct=30,time=1,mindist=50,maxdist=500, type=’enemy’,subtype='none', situation='none', role='none', priority=2, movetype='move'))

 

Move to a random point between mindist and maxdist away.

 

 

 

TSpreadOut(pct=30, time=1, mindist=100, maxdist=200, type='friend', subtype='none', situation='none', role='none', priority=2)

 

If within mindist of an ally, move to an object up to maxdist away.

 

 

TTeleportAway(power,pct=30,energy=0,mindist=100,maxdist=400,type='enemy', subtype='none',situation='none',role='none',priority=5)

 

Teleport away from enemies within mindist, to an object not more than maxdist away.

 

 

TTeleportTo(power,pct=30,energy=0,mindist=100,maxdist=400,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Teleport to enemies more than mindist but not more than maxdist away.

TTumbleAway(power, pct=30, time=1, energy=0, mindist=100, maxdist=400, type='enemy', subtype='none', situation='none', role='none', priority=2)

 

If an enemy comes within midist, tumble to an object not more than maxdist away.

 

 

TTumbleTo(power, pct=30, time=1, energy=0, mindist=50, maxdist=200, type='enemy', subtype='none', situation='none', role='none', priority=2)

 

Use a tumble power to move to an enemy more than mindist, but not more than maxdist away.

 

 

 

 

Offensive Tactics

 

TAreaAttack(power, pct=20, time=3, energy=0, mindist=0, maxdist=80, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Perform an area attack if an enemy is within range (maxdist) and no friendly characters are within range – no friendly fire.   You can set the type to ‘friend’ and it will only use the tactic if friends are within range, and no enemies.

 

 

 

TBalance(power, pct=20, time=3, energy=0, mindist=0, maxdist=300, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

If an enemy is between mindist and maxdist away, and that enemy has more health than me, use a Balance type of power (steal health from them and give it to me).

 

 

TChargeUp(power, pct=20, time=2.5, energy=0, mindist=30, maxdist=100, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Use a charge-up power (think Minute Man’s 300 Percenter) if not already charged-up.

 

 

TClone( power, pct=20, time=3, energy=0, situation='none', role='none', priority=5)

 

Use a cloning power.  After the power is used, find the clone and make sure it has all of the proper  proper internal values set.  This is used to make sure the clone is put on the right AI ‘team’ and gets the proper custom AI if there is one defined.   One important point, clones cannot use this power to create more clones.

 

 

TDirectAttack(power, pct=20, time=3, energy=0, mindist=0, maxdist=300, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Use a direct attack upon an enemy within range. 

 

 

TDisruptObject(power, pct=20, time=3, energy=0, mindist=100, maxdist=300, type='enemy', radius=100, subtype='none', situation='none', role='none', priority=5)

 

Use a disruption power on an object within radius distance of an enemy.  In other words – see enemy, find nearby object, blow up object.

 

 

TElectrify(power, pct=30, time=0.7, energy=0, mindist=50, maxdist=200, type='enemy', subtype='none', situation='none', role='none', priority=5, radius=100)

 

Use the electrify power (it is something like speeding bullet, but does a kind of electrical explosion as well).  Make sure no friends are within radius distance of the enemy being targeted.

 

 

TEmpathy(power, pct=50, time=2.5, energy=0, mindist=30, maxdist=300, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

For use with empathy powers.  Use empathy but only if empathy isn’t already in use.

 

 

TInvisibility(power, pct=20, time=0.5, energy=0, mindist=0, maxdist=300, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Turn invisible

 

 

TInvisibilityFlee(power, pct=20, time=1, energy=0, mindist=100, maxdist=500, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Turn invisible if an enemy comes within mindist, and flee from them.

 

 

TMeleeAttack(power, pct=30, time=3, energy=0, maxdist=40, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Use a melee attack upon an enemy within range.

 

 

TMeleeAttackAir(power, pct=40, time=3, energy=0, maxdist=150, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

If an enemy is flying, then use a melee attack on them.  Note that the melee attack supplied must have the Melee: Airborn Targets Only flag checked within the editor.

 

 

TMeleeArea(power, pct=50, time=3, energy=0, maxdist=50, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Use a melee attack if there are 2 or more enemies within range, and no friendlies in range.

 

 

 

TRangedAttack(power, pct=20, time=2.5, energy=0, mindist=30, maxdist=300, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Use a ranged attack on an enemy between mindist and maxdist away.

 

 

 

TRangedExplosive(power, pct=20, time=3, energy=0, mindist=20, maxdist=300, type='enemy', radius=100, subtype='none', situation='none', role='none', priority=5)

 

Use a ranged attack that explodes when it hits.  The character will try to ensure that no friendlies are within range of the explosion.  Set the radius to the size of the explosion. 

 

 

 

TSpeedingBullet(power, pct=30, time=0.7, energy=0, mindist=50, maxdist=200, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Use the speeding bullet power to attack an enemy within range.

 

 

TThrow(pct=30,time=2,mindist=100,maxdist=400,type='enemy', subtype='none', situation='none', role='none', priority=5, objdist=300)

 

Pickup and throw objects at enemies between mindist and maxdist away.  Move towards objects that can be thrown if they are not more than objdist away.

 

 

FFX Tactics

 

Use these if the character has the corresponding attributes.

 

 

TFireControl(pct=30,energy=25,mindist=120,maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Use fire control on an enemy (put up a wall of flame in front of them).

 

 

TIceControl(pct=30,energy=25,mindist=120,maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Use ice control.  Randomly put up a wall of ice, or put down a patch of ice.

 

 

TSummon(pct=30,energy=25,mindist=0,maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Use the summon attribute.  Summon a random type of character from the summon list.

 

 

TExplosive(pct=25,energy=33,mindist=0,maxdist=80,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Use the explosive attribute.

 

 

TWeatherControl(char, string2, flt, user, pct=20, energy=50, mindist=0, maxdist=80,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Use weather control. Randomly call down either lightning or hail if an enemy is between mindist and maxdist away.

 

 

TEnergyShield(pct=80, time=4, energy=25,situation='none',role='none',priority=10)

 

Put up an energy shield, if the energy shield is not already in place.

 

 

TGaseousForm(power='OnGaseousForm', pct=60, time=4, energy=25,mindist=0, maxdist=200,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Use a gaseous form if an enemy is within maxdist away.  Power determines the power to use.

 

 

TAntiWarZone(pct=25, time=3, energy=25,mindist=0, maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Turn projectiles into flower petals.  Turn on the anti-war zone field if it isn’t already on.

 

 

TPuppetMasterU(pct=60, time=4, energy=25,situation='none',role='none',priority=5)

 

Animate urban objects.

 

TPuppetMasterNpct=60, time=4, energy=25,situation='none',role='none',priority=5)

 

Animate nature objects.

 

 

TEnvLocal(pct=50, time=3, energy=50, mindist=50, maxdist=200, type='enemy', radius=50, subtype='none',situation='none',role='none',priority=5)

 

Local environmental control.

 

 

TEnvGlobal(pct=60, energy=50, mindist=0, maxdist=200,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Global environmental control.

 

TLivingLaser(pct=30,time=3,energy=50,mindist=100,maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=10)

 

Use living laser to move to an enemy more than mindist, but less than maxdist away.

 

TLivingLaserToObject(pct=30,time=3,energy=33,mindist=100,maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=10)

 

Use living laser to move to an object instead of an enemy (escape).

 

 

TPlasmaSculptorBarrier(pct=20,time=3,energy=33,mindist=100,maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=10)

 

Use plasma sculptor to form a barrier in front of an enemy.

 

 

TPlasmaSculptorDrop(pct=20, time=3, energy=0, mindist=50, maxdist=200, type='enemy', radius=50, subtype='none', situation='none', role='none', priority=5)

 

Use plasma sculptor to drop an object on an enemy.

 

 

TSandstorm(pct=30, time=3, energy=33, maxdist=100, type='enemy', subtype='none', situation='none', role='none', priority=10)

 

Turn into a sandstorm.

 

 

TMimic(charpct=50,time=5,energy=0,mindist=20,maxdist=200,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Turn into a copy of an enemy.

 

 

TShapeShiftRandom(pct=15,time=5,energy=25,mindist=20,maxdist=200,situation='none',role='none',priority=5)

 

Shapeshift into a random form (from the list defined for the shapeshift attribute).

 

 

TShapeShiftForDistance(newForm=1,pct=70,time=5,energy=25,mindist=200,maxdist=500,subtype='none',situation='none',role='none',priority=5)

 

Shift into form number newForm if an enemy is far away.

 

TShapeShiftForMelee(newForm=1,pct=50,time=5,energy=25,mindist=0,maxdist=80,subtype='none',situation='none',role='none',priority=5)

 

Shift into form number newForm if an enemy is close by.

 

 

TShapeShiftForHealing(newForm=1,pct=50,time=5,energy=25,mindist=0,maxdist=80,subtype='none',situation='none',role='none',priority=5)

 

Shift into form newForm if health is less than 25% of maximum.

 

 

TShapeShiftForFliers(newForm=1,pct=50,time=5,energy=25,mindist=0,maxdist=200,subtype='none',situation='none',role='none',priority=5)

 

Shift into form newForm if facing a flying enemy.

 

 

TSuperLeap(pct=30,time=1.5,energy=0,mindist=80,maxdist=400,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Leap to an enemy.

 

 

TTK(pct=50, time=3, energy=25, maxdist=300, type='enemy', subtype='none', situation='none', role='none', priority=5)

 

Use telekinesis powers.

 

 

TEarthSpike(pct=20,time=3,energy=33,mindist=100,maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=10)

 

Throw up an earth spike beneath an enemy.

 

 

TEarthWall(pct=20,time=3,energy=33,mindist=100,maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=10)

 

Put up an earth wall between you and the enemy.

 

TMagnetic(pct=70,time=3,energy=33,mindist=40,maxdist=300,type='enemy',subtype='none',situation='none',role='none',priority=10)

 

Use magnetic powers to repel or attrack metal characters.

 

TMassControl(pct=100,time=1,energy=0,mindist=0,maxdist=500,type='enemy',subtype='none',situation='none',role='none',priority=5)

 

Use mass control.  Become light if the enemy is far away, become heavy if they are close.

 

 

TAbsorber(pct=30,time=1,energy=20,mindist=0,maxdist=100,subtype='none',situation='none',role='none',priority=5)

 

Absorb the properties of nearby objects.

 

 

 

 

Hybrid Characters: Which Game AI to Use?

 

I find that I regularly make use of a small number of game AIs.

 

  • CThugGren:  this is my most commonly used one.  It uses two powers, can flank enemies and is fairly aggressive.  The powers are listed as being melee in the first slot and ranged in the second slot, but I’ve found that it will use two melee powers just as well.  This AI also works great with flyers, since it doesn’t feel the need to land very often.
  • CDoppelCop:  use a ranged attack and flee melee attacks by flying.  It is pretty good, but it has a tactic that forces the AI to land if it feels it is safe, rather than staying in the air.
  • CIceQueen and CDupeMinuteMan:  these are for strong melee types.  They will also throw things, which is the main reason to use them.
  • CEvilMicrowave:  if you have a character that needs to teleport, this is the only AI that can do it. 
  • CPurpleDarkman:  I use this AI for character that need to turn invisible as it does so fairly reliably.

 

 

Building a Completely New, Scripted AI

 

Yes, it can be done.

 

Building a custom AI is almost identical to enhancing an AI.   When building a new AI, you should set the ‘timer’ parameter to ‘auto’  (e.g.  [‘timer’,’auto’,…]). 

 

That’s it.   

 

From a practical standpoint, you should consider what situations your character will find itself in and put in appropriate tactics.  For example, what happens when they meet a flying enemy?

 

 

 

 

Examples

 

 

The Human Torch should fly around, blast enemies with ranged attacks and flee into the air if enemies get too close.

 

I use the CThugGrenade AI for him in the Fan4 mod. Tier A, slot 1, I have his melee attack and in slot 2 I have a ranged flame attack.   The game AI will do most of the work of moving around and attacking, but it won’t use his other attacks, his defense, or fly, so I have to add those as extensions.  I want him to act as follows:

 

If in extreme danger, use an active defense and fly away.

 

If being swarmed, use a supernova attack, but only do so very rarely.

Otherwise, if an enemy is to close, get into the air and move away.

Otherwise, occasionally try an explosive nova attack.

Otherwise, sometimes try an explosive fireball attack.

Otherwise, sometimes fly to a random point (get into the air).

 

['humantorc_evil',

     ['danger',

          "TActiveDefenseRandFly('human_torch Fire Shield',energy=25)",

     ],

     ['timer',3,

          "TAreaGroup('human_torch Supernova',pct=5,time=5,energy=100)",

          "TFleeMeleeFly()",

          "TRangedExplosive('human_torch Nova',energy=75,maxdist=250,radius=90)",

          "TRangedExplosive('human_torch Fire Balls', energy=35)",

          "TRandFly(pct=30)",

     ],

],

 

 

 

 

Mr. Fantastic also use CThugGren, with a melee and a ranged ‘stretch punch’ attack in the two power slots.  I want him to be able to ‘stretch’ away from danger, and fight somewhat intelligently.

 

If in danger, sprint away.

 

If no friendlies are in the way, try to use an area stasis attack on nearby enemies.

Otherwise, try to do a power null on a nearby enemy (if not already nulled).

Otherwise, try a melee attack.

 

['mrfantast_evil',

     ['danger',

          "TDangerSprint(mr_fantastic Sprint’,energy=25)",

     ],

     ['timer',3,

          "TAreaStasis('mr_fantastic Elastic Coils',energy=50)",

          "TRangedPowerNull('mr_fantastic Nullifier',energy=50)",

          "TMeleeAttack('mr_fantastic All Around',energy=25)",

     ],

],

 

 

 

The Thing uses CDupeMinuteMan, so that he throws objects at both air and ground targets.  I only modified this one slightly, to use his attacks more intelligently.

 

If being ganged up on, use a melee attack that affects an area.

Otherwise, if a nearby enemy is flying, try to swat them out of the air.

 

['thing_evil',

    ['timer',2,

         "TMeleeArea('thing Knockback',energy=10)",

         "TMeleeAttackAir('thing Swat',energy=10)",

    ],

],

 

 

 

The Invisible Woman uses CPurpleDarkman (for invisibility), with the area attack for the game AI set to her ranged stasis attack.  I did that so she will use her stasis attack most often, and I simply have to augment her other powers.

 

Use the invisible shield if in danger.

 

If being swarmed by enemies, use an area attack (toss them into the air).  Note that AreaGroup has a high default percentage chance of being used.

Otherwise, try the area attack anyway (at a lower default percentage chance), as it is one of her more effective attacks.

Otherwise, try a ranged attack if my nearest enemy is in range.

Otherwise, occasionally fly into the air.

 

['inviswomn_evil',

     ['danger',

          "TActiveDefenseRandMove('iw Shield',pct=40,energy=25)",

     ],

     ['timer',3,

          "TAreaGroup('iw Toss',energy=25)",

          "TAreaAttack('iw Toss',energy=25)",

          "TRangedAttack('iw Bubbles',energy=10)",

          "TRandFly(pct=10)",

     ],

],

 

 

Angel of the XMen is set up with the CDoppelCop AI with a melee attack in place of the ranged attack that the AI usually requires (it works nicely).  This produces a character that does hit and run melee attacks.

 

Angel has a lot of flying tactics, in order to maximize the use of his wings.  I have him set up to:

 

Use a flying ram tactic to knock enemies out of the air.

Otherwise, fly to an enemy (to engage them in melee) if far enough away.

Otherwise, if being swarmed by enemies, try an area attack.

Otherwise, if in melee range, try a melee attack (there are two there.)

Otherwise, occasionally try to fly.

 

 

['angel_evil',

     ['timer',3,

          "TFlyRam()",

          "TFlyTo(type='enemy')",

          "TAreaGroup('angel wing smash',energy=25)",

          "TMeleeAttack('angel Bash',energy=10)",

          "TMeleeAttack('angel Knockback',energy=10)",

          "TRandFly()",

     ],

],