Difference between revisions of "Combat AI"

From Divinity Engine Wiki
Jump to: navigation, search
(Skills)
 
(6 intermediate revisions by 2 users not shown)
Line 21: Line 21:
 
# In the end only one <i>Action</i> will be on top. We have a skill (or default attack), a target, a position, and even the path has been checked. The action will be fetched from script and executed.
 
# In the end only one <i>Action</i> will be on top. We have a skill (or default attack), a target, a position, and even the path has been checked. The action will be fetched from script and executed.
 
# What if we don't have any <i>Action</i> that is deemed positive? That's when the fallback action kicks in. The fallback action tries to find a good position for the character and walks there.
 
# What if we don't have any <i>Action</i> that is deemed positive? That's when the fallback action kicks in. The fallback action tries to find a good position for the character and walks there.
 
  
 
=Guiding Ai=
 
=Guiding Ai=
Line 77: Line 76:
 
<br />
 
<br />
 
===Tags===
 
===Tags===
 +
Sometimes you'd like to make sure Ai prefers a target, or doesn't, or even totally ignores a target. There are some tags you can set on objects to make it work:
 +
<ul>
 +
<li>AI_PREFERRED_TARGET: boosts any score on this target. This will not only increase being attacked by enemies, but also being healed by allies</li>
 +
<li>AI_UNPREFERRED_TARGET: decreases any score on this target. This will not only decrease being attacked by enemies, but also being healed by allies</li>
 +
<li>AI_IGNORED_TARGET: completely ignored by Ai. Damage doesn't matter, healing doesn't matter, killing doesn't matter.</li>
 +
</ul>
  
 
=Overriding Ai=
 
=Overriding Ai=
Line 87: Line 92:
 
<li>Summon skills: Ai does not know what kind of impact a summon will have. The AiCalculationSkillOverride skill will be used to calculate the impact of the summon.</li>
 
<li>Summon skills: Ai does not know what kind of impact a summon will have. The AiCalculationSkillOverride skill will be used to calculate the impact of the summon.</li>
 
<li>Projectile skills with a filled in SpawnObject: Just like with Summon skills Ai does not know what kind of impact a summon will have. The AiCalculationSkillOverride skill will be used to calculate the impact of the summon.</li>
 
<li>Projectile skills with a filled in SpawnObject: Just like with Summon skills Ai does not know what kind of impact a summon will have. The AiCalculationSkillOverride skill will be used to calculate the impact of the summon.</li>
 +
<li>Target skills: The AiCalculationSkillOverride skill will be used to calculate the score on the target.</li>
 +
<li>Rain and Shout skills: The AiCalculationSkillOverride skill will be used on all targets that would get hit by the original skill to calculate the score on the target.</li>
 
</ul>
 
</ul>
 
Next to Summon and Projectile skills it is also supported by Shout and Target skills.
 
Next to Summon and Projectile skills it is also supported by Shout and Target skills.
 
<br />
 
<br />
The override skill can be fairly simple, just like the Target_DummyTargetSkill that we use in a couple of cases. However, it's advised to make the override skill as accurate as possible. E.g.: for a Summon skill that spawns a summon that does only fire damage you shouldn't use an override skill that only does physical damage. Ai might then cast the summon in the middle of a group of enemies that are all immune to fire damage. Use a target skill that represents the actual summon as accurate as you possibly can.  
+
The override skill can be fairly simple, just like the Target_DummyTargetSkill that we use in a couple of cases. However, it's advised to make the override skill as accurate as possible. E.g.: for a Summon skill that spawns a summon that does only fire damage you shouldn't use an override skill that only does physical damage. Ai might then cast the summon in the middle of a group of enemies that are all immune to fire damage. Use a target skill that represents the actual summon as accurate as you possibly can.
 +
 
 
====AiFlags====
 
====AiFlags====
 
The AiFlags column is used to set flags specifically for Ai. A list of the flags and what they do can be found [[CombatAi_AiFlags|here]]. It is possible to use multiple flags by concatenating them with a semicolon (';').
 
The AiFlags column is used to set flags specifically for Ai. A list of the flags and what they do can be found [[CombatAi_AiFlags|here]]. It is possible to use multiple flags by concatenating them with a semicolon (';').
 
===Scripting===
 
===Scripting===
 +
Overriding Ai with scripting is relatively easy: make sure the priority of your REACTION is higher than 60 (higher than all REACTIONs related to Ai) and the Ai won't execute anymore.
  
 
=Unsupported properties=
 
=Unsupported properties=
 +
Some skill and status properties are not supported for Ai. If it's not supported Ai will ignore the property altogether and it might do unexpected things. Try to avoid these properties for Ai and use the <i>CanNotUse</i> [[#AiFlags|AiFlag]] to prevent the Ai from casting any skills with these properties.
 
===Skills===
 
===Skills===
 +
<ul>
 +
<li>Chaos damage type (random damage type)</li>
 +
<li>Spawning multiple summons</li>
 +
<li>Zone skills with a push distance</li>
 +
<li>Shout skills with a push distance</li>
 +
<li>Skills with the Sabotage property</li>
 +
<li>Skills with the Equalize property</li>
 +
<li>Teleportation skills with the SwapSurfaces property</li>
 +
<li>Skills with the CreateConeSurface property</li>
 +
<li>Projectile skills with an angle and multiple targets</li>
 +
</ul>
 +
 
===Statuses===
 
===Statuses===
 +
<ul>
 +
<li>Surface absorption boostst</li>
 +
<li>Adding skills</li>
 +
<li>The statuses STANCE, SMELLY, CLEAN, DARK_AVENGER, REMORSE, UNHEALABLE, CHANNELING, INFUSED, LINGERING_WOUNDS, SPIRIT_VISION, FORCE_MOVE, DEMONIC_BARGAIN, FLOATING, CHALLENGE, and EXTRA_TURN</li>
 +
<li>Consume statuses that set weapon overrides</li>
 +
<li>Consume statuses that reset cooldowns</li>
 +
</ul>

Latest revision as of 14:21, 13 March 2018

Introduction

Ai 2.0 or, as we'd like to call it, Jane (used to be an abbreviation, but we already forgot about it the next day) no longer uses a script for every single skill to reason about its usage. Almost all logic has been moved to code, and all that's left in script is starting the Ai calculation, stopping the Ai calculation, and executing the action that has been selected by Ai. This script logic can be found in DefaultBehaviour.charScript. The Ai now takes into account the properties of a skill, the statuses that are applied, the weapons that are used, the items nearby, etc. Besides being smarter in general it also fixes a lot of issues with Ai ending turns we had in D:OS. It (attempts) to simulate what's going to happen if it will use a certain skill at a certain target and assign a score to it. The action with the highest score will be executed. All this happens automatically, so a new skill or status can be used by Ai without any extra steps. Of course, there are exceptions, and you'd still like to guide or override the Ai from time to time. That's what this page tries to cover in detail.

How does it work

When trying to guide or override the Ai it's useful to know why the Ai is doing what it's doing. I'll try to explain the general approach the Ai takes in one turn to decide what action it will take, and try to refrain from using too many implementation details. First of all, let me explain a couple of terms up front that might also also be useful when touching archetypes and modifiers:

  • Action: walking to a position (if needed) and using a skill on one or multiple targets, or a fallback (finding a preferable position if no other action is viable)
  • ActionScore: the score of the use of a skill
  • PositionScore: the score of a position, based on surfaces that may be on that position, allies or enemies in the vicinity, etc.
  • MovementScore: the score of moving from A to B, based on PositionScores on the path from A to B
  • ActionCostModifier: the modifier combined from multiple modifiers that determines the total 'action cost' of an action, including AP and SP
  • CostModifier: the modifier combined from multiple modifiers that determines the total 'cost' of an action. Affected by e.g. items being used, cooldowns, etc.


Let's say the Ai has the Projectile_Fireball skill and go through the steps that the Ai takes to calculate the scores for possible actions:

  1. Check first: can we cast this skill? Skill conditions, cooldowns, difficulty mode, statuses preventing us from casting, etc. No need to calculate anything if we can't even cast.
  2. Find interesting targets to cast the skill on. Ai checks for characters, items (barrels could explode), and positions on the terrain. We run a simulation on each of these targets to see what effect it will have. This simulation on every target gives us damage scores, health scores, buff scores, etc. for every object we hit (the ActionScore).
  3. Calculate the 'final' score of every Action (at this point this is purely the skill being casted). The different scores are thrown together, affected by a whole bunch of target specific modifiers, and balanced so that we end up with one single value for the score.
  4. Only the interesting Actions, based on the 'final' score in the previous step, will be investigated further. We start to find a good position to cast from. The character might not be able to cast from it's current position (out of sight, out of range, etc.), or the character might not like its current position due to nearby enemies. PositionScores will be calculated and we hope to find a good position for every action.
  5. After finding a good position we start calculating the MovementScore. Does the character need to walk through a fire surface? Could we jump instead of walking? Do I have enough AP to even walk there this turn?
  6. In the end only one Action will be on top. We have a skill (or default attack), a target, a position, and even the path has been checked. The action will be fetched from script and executed.
  7. What if we don't have any Action that is deemed positive? That's when the fallback action kicks in. The fallback action tries to find a good position for the character and walks there.

Guiding Ai

There are multiple ways to guide Ai into certain actions or behaviour. Skill conditions, archetypes and modifiers, and AiHints are all supported by Ai and are used by Ai during the score calculation. Any other way to guide Ai might result in incorrect behaviour (but you're welcome to try).

Skill conditions

CombatAi SkillConditions.PNG

The skill conditions panel you get when adding a skill to a character

The skill conditions panel can be used to set conditions for casting a skill (e.g. prohibit using a skill if the caster is still full health), set flags for the skill, or apply a simple score modifier.

  • AiFlags: AiFlags can be set on a skill on a global level, but they can also be set in the skill conditions. A list of the flags and what they do can be found here. It is possible to use multiple flags by concatenating them with a semicolon (';')
  • MinimumImpact: The skill should impact at least this amount of characters in a positive way, or else it can not be used. Positive in this case means it's benefitial for the caster: e.g. healing an ally, or damaging an enemy
  • OnlyCastOnSelf: The skill can only be cast on self. Can be used, for example, to force a character to only use the bless skill on itself
  • StartRound: The skill can only be used from this round. Everything below and including 1 means it can be used from the start
  • HasNoMagicalArmor: The skill can only be used if the source/target has no magical armor
  • HasNoPhysicalArmor: The skill can only be used if the source/target has no physical armor
  • MaximumHealthPercentage: The skill can only be used if the source/target has a health percentage lower or equal to this value
  • MinimumHealthPercentage: The skill can only be used if the source/target has a health percentage higher or equal to this value
  • Tags: The skill can only be used if the source/target has these tags

You may have noticed that the italic conditions in above list are listed twice in the skill conditions. It's possible to set these for both the source (the caster of the skill) and the target of the skill (if the skill has a direct target). Tip: Tags can be used for any skill condition that is not part of the standard skill conditions. You can create a custom tag and a script that assigns/removes a tag based on scripted conditions.
The last skill conditions are the difficulty modes. These are simple checkboxes to enable/disable a skill on a certain difficulty. The very last thing on the list, the score modifier, is exactly what it says it is: a score modifier. If you want the Ai to use a skill more often, even if it's not that good at all, you could increase the score modifier. You could also use to, for example, force Ai to cast a certain skill after an event: set a high score modifier and set a source tag condition for a tag that you apply via script.

Archetypes and modifiers

CombatAi Archetype.PNG

The EXTERN script variable that sets the archetype

The EXTERN Archetype parameter in the DefaultBehaviour script allows you to set the archetype of a character. It can also be set using the CharacterSetArchetype call in script. Archetypes are linked to a text file that contain modifiers for Ai. These modifiers are used when calculating the scores for all the skills and are delicately balanced. And you can change them.
You can find the archetype files in: Public/YourMod/AI/Archetypes/ (if the directory doesn't exist you can just create it yourself). All .txt files in the Archetypes folder will be shown as options in script. The archetypes in this folder are used for Explorer and Classic mode. If you want to override modifiers from archetypes for Tactician and Hardcore mode you can place these in a folder called TACTICIAN inside the Archetypes folder. So, let's say we want to override a modifier in the base archetype (an already existing archetype in D:OS2). We'd have to create a new text file called base.txt and give it the following content:

// We want self-healing to be more common in our mod -> yes, comments work in these files!
MULTIPLIER_HEAL_SELF_POS          10.0 // This will override the modifier MULTIPLIER_HEAL_SELF_POS located in the D:OS2 base archetype with our own value of 10.0. Only int and float values are allowed in these files

Or we'd like to create a completely new archetype called myFirstArchetype. We'd have to create a text file called myFirstArchetype.txt and give it the following content:

// We copy over all modifiers from the base archetype because we don't want to specify every single modifier
USING base

MULTIPLIER_HEAL_SELF_POS          10.0 // Because I'm unoriginal

If you place a .txt file containing the above snippet in your Archetypes folder you'll have the archetype myFirstArchetype showing up in script.
The only information you're still missing now is a list of all the modifiers and archetypes and what they do. You can find that list right here.

AiHints

CombatAi AiHints.PNG

The EXTERN script variables AiHints and StayInAiHints

You can assign a tag to the EXTERN AiHint parameter in the DefaultBehaviour script for the Ai to use. Ai will find AiHintAreaTriggers with this tag and use these during the calculation. The AiHintAreaTriggers with the specified tag (referred to ai AiHints from now on) are areas where the Ai would prefer to stand when attacking. You could use this when you, for example, want a ranger to prefer standing on some platforms in the back instead of on the lower ground. Keep in mind that it does not force the Ai to stay in the AiHint. For that you also need to enable the StayInAiHints parameter in the same DefaultBehaviour script. This forces the Ai to always stand in the AiHint, even if it blocks it from attacking. There's only 2 exceptions to this rule:

  1. All of the AiHints are filled with dangerous surfaces (all of them full of fire for example)
  2. The character has been moved outside of the AiHint (started outside of it or has been teleported for example) and is not able to attack anyone from any AiHints. In this case it will try to attack anyone without moving.


Tags

Sometimes you'd like to make sure Ai prefers a target, or doesn't, or even totally ignores a target. There are some tags you can set on objects to make it work:

  • AI_PREFERRED_TARGET: boosts any score on this target. This will not only increase being attacked by enemies, but also being healed by allies
  • AI_UNPREFERRED_TARGET: decreases any score on this target. This will not only decrease being attacked by enemies, but also being healed by allies
  • AI_IGNORED_TARGET: completely ignored by Ai. Damage doesn't matter, healing doesn't matter, killing doesn't matter.

Overriding Ai

It's strongly advised to not override the Ai, but we understand that it's needed from time to time. Below are some supported ways to override the Ai and some tips and tricks you might want to use.

Skills

The skills in SkillData have several properties that affect the Ai in a special way.

Skill overrides

Several skill types have the possibility to be overwritten with the score of a specified Target skill (can not be of any other type) in the AiCalculationSkillOverride column. If a skill has an override it will calculate the score by simulating with the Target skill instead of the original skill. This can be used to make the Ai think a skill will do something that it won't actually do, but some skills actually need to have an override skill:

  • Summon skills: Ai does not know what kind of impact a summon will have. The AiCalculationSkillOverride skill will be used to calculate the impact of the summon.
  • Projectile skills with a filled in SpawnObject: Just like with Summon skills Ai does not know what kind of impact a summon will have. The AiCalculationSkillOverride skill will be used to calculate the impact of the summon.
  • Target skills: The AiCalculationSkillOverride skill will be used to calculate the score on the target.
  • Rain and Shout skills: The AiCalculationSkillOverride skill will be used on all targets that would get hit by the original skill to calculate the score on the target.

Next to Summon and Projectile skills it is also supported by Shout and Target skills.
The override skill can be fairly simple, just like the Target_DummyTargetSkill that we use in a couple of cases. However, it's advised to make the override skill as accurate as possible. E.g.: for a Summon skill that spawns a summon that does only fire damage you shouldn't use an override skill that only does physical damage. Ai might then cast the summon in the middle of a group of enemies that are all immune to fire damage. Use a target skill that represents the actual summon as accurate as you possibly can.

AiFlags

The AiFlags column is used to set flags specifically for Ai. A list of the flags and what they do can be found here. It is possible to use multiple flags by concatenating them with a semicolon (';').

Scripting

Overriding Ai with scripting is relatively easy: make sure the priority of your REACTION is higher than 60 (higher than all REACTIONs related to Ai) and the Ai won't execute anymore.

Unsupported properties

Some skill and status properties are not supported for Ai. If it's not supported Ai will ignore the property altogether and it might do unexpected things. Try to avoid these properties for Ai and use the CanNotUse AiFlag to prevent the Ai from casting any skills with these properties.

Skills

  • Chaos damage type (random damage type)
  • Spawning multiple summons
  • Zone skills with a push distance
  • Shout skills with a push distance
  • Skills with the Sabotage property
  • Skills with the Equalize property
  • Teleportation skills with the SwapSurfaces property
  • Skills with the CreateConeSurface property
  • Projectile skills with an angle and multiple targets

Statuses

  • Surface absorption boostst
  • Adding skills
  • The statuses STANCE, SMELLY, CLEAN, DARK_AVENGER, REMORSE, UNHEALABLE, CHANNELING, INFUSED, LINGERING_WOUNDS, SPIRIT_VISION, FORCE_MOVE, DEMONIC_BARGAIN, FLOATING, CHALLENGE, and EXTRA_TURN
  • Consume statuses that set weapon overrides
  • Consume statuses that reset cooldowns