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.
Step
1: Setting up the character in the editor
The
Order of Tactics in a List
Tactics
have a ‘Percent to Use’ Parameter
Hybrid
Characters: Which Game AI to Use?
Building
a Completely New, Scripted AI
NOTE: You must have FFX 2.3 installed for the AI to work.
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.
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:
If you are just creating a new AI for the Danger Room, simply:
Using the AI in a mod is a little more complex, but still easy.
That’s it. You’re ready to go.
A trigger is an event that causes the AI to evaluate a set of tactics. There are several triggers currently defined.
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:
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
],
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.
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).
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’,
[‘target’,
“TargetSubtype(subtype=[’not frozen’,’not blanked’])”,
],
],
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.’
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)",
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.
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.
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:
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.
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.
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:
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
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
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.
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
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.
T
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
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
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.
I find that I regularly make use of a small number of game AIs.
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?
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()",
],
],