I’m back and working on the next version of the Companion and Monster AI

There would be some issues with enemy location setting (used to find PC party members if they stealth or go invisible) and dealing with creatures on the other sides of doors. There could be some other minor issues from the quick look I did. Most of the AI is in a script called script hench_o0_ai so most functionality would be OK. I also think that compiling the script with the latest version of the AI would work fine with the older version that is part of the base install.

I would suggest looking at overriding the hench_o0_initialize script instead. This script is already run once by the AI for enemy monsters at the start of combat. It creates items and does some prebuffs of monsters if the AI global options are set. It does not have the PC object, but that can be obtained by calling GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_CONTROLLED, OBJECT_SELF, 1, CREATURE_TYPE_IS_ALIVE, CREATURE_ALIVE_BOTH) - maybe different parameters if you want the PC only. There are some rare monsters that can run the AI without a PC present, in that case call DeleteLocalInt(OBJECT_SELF, “HenchAutoIdentify”) in the script to rerun it until you get a PC. Just make sure the original code in the script is only run only once. If you override hench_o0_initialize, use the latest scripts from the 2.4 AI, it has some bugfixes and will work with no issues in the base AI.

1 Like

Tony, I found workaround how to technically make AI companions use given spells from items. Your suggestion works this way, I found a very nice tool https://neverwintervault.org/project/nwn2/script/charlies-item-modifier so when I find an item who has spell use per day I simply use console command giveitem nw_WMGMRD003 so it gives rod of terror with 2 spells per day. Using item modifier I can remove unwanted spells and add my spell use per day which is on the item (helmet, armour or so on). And then I put charges on the rod using the same tool. So in this way AI companions using a rod as they would have a spell in reality even if they are not casters while original item (helmet or other is equipped with additional stats). I tried to do the same way with other equipped items like a helmet and put charges on it with spell per day but they don’t use this way.

The AI could automatically add one charge to such items, but when examined the single charge is shown (no workaround as far as I know). Could be done as a global option.

Is it possible to implant the same function make AI companions use items as the enemy do? (by copying the equipped items casting properties onto wands that the AI names the same as the original item).

It is possible to do this but keeping track of the copied items would be difficult to impossible. The original item could be unequipped, sold or given to another companion. For this reason, I wouldn’t want to do the workaround.

Progress report:

  • Finished dragon casting but still working on example dragons using the system. Also will give reworked persistent aura spell scripts for dragon fear, hezrou stench, and ghast stench in the example. Fixes issues with dispel magic removing area of effect object and effects applied. Only one save needed per aura, previous save used when you reenter. Auras also properly scale with monster hit dice and ability modifier.

  • Improved spell talent search routines. Getting sub spells should work better, especially protection from element spells that have five sub spells for the element types.

  • Fixes and improvements in use of feint and knockdown. Added support for flourish and impromptu sneak attack.

  • Have AI account for greater restoration full heal of target.

  • Fixed issue with persistent aura spells being cast more than once.

Also looking at some long standing bugs like bard fascinate note working to see if they can be fixed.

Fixes and improvements in use of feint and knockdown. Added support for flourish and impromptu sneak attack.

Good to see more missing abilities are being supported now.

Tony, create Patreon, I want to support your work on updating AI :raised_hands: :mechanical_arm:

1 Like

BUG: I’m playing as favored soul which has spontaneous casting. Everything was more-less fine (from some level FS wasn’t very interested in melee fights at all since got some offensive spells even if I set him on Scaled spellcasting setting and even if he got pretty nice melee weapon and very good AC he was standing around and more interested in healing or buffing even enemy is not very dangerous, sometimes he just standing and do nothing even he is attacked.) The serious bug occurred when he got Ethereal Jaunt spell. Every new battle he tries cast Ethereal Jaunt first to buff which is fine and logical if the enemy is powerful. But he casts Ethereal Jaunt and then lesser spell mantle and stand still doing nothing at all while he is in Ethereal, sometimes he casts few more spells to buff but after that stand still and not even continuing buffing with other buffs. Even if I give him command attack nearest it doesn’t react and does nothing. Once or if Ethereal Jaunt spell is not available he continues using other buffs and tries to fight as normal and using some buffs with extended duration. Here is a save game, where I made familiar which has Ethereal Jaunt mode so enemy will not be interested while you can control familiar while you can watch how main character’s AI fight against Light of Heaven 1vs1.

UPDATE: I was using mod altogether with Kaedrin’s PrC pack 1.41.4, when I do remove this mod looks like it solves a little bit problem and he buff himself more than just spell mantle but not much only with several more. And then he tries to cast some offensive spells but when run out he doesn’t fight with melee at all now, only defends and not attack with the weapon only healing spells and potions uses in this stage. When I click attack nearest enemy he starts to cast offensive spell or attack with melee weapon but only for 1 or few rounds and then he doesn’t fight again only defends. Clicking on attack nearest enemy again he starts do something again but only for 1 or few rounds then stands still. I’m thinking this happens because he failing a lot with concentration checks and maybe he is afraid to cast anymore spells. But even so, he doesn’t fight with melee.

I’m using Latest 2.4 version. For further investigation I checked the files and found that if I remove hench_o0_ai.ncs from the mod, AI doesn’t act like described. But if think this is the main file for new AI and without it AI no longer use extended spells.

1 Like

Thanks for the save game.

I have found a few AI issues with saved game. The AI should not be trying to do spontaneous metamagic casting with your favored soul with one level of cleric. During the lockup, the AI is trying to cast blessed aim because it is allowed as a cleric but not known as a favored soul or memorized as a cleric. This is now fixed. The AI is also identifying the 16th level divine champion as a spell casting threat because the AI is using Kaedrin’s modification that allows divine champions to increase spellcasting ability every other level. The routine needs to be adjusted to not consider paladin or ranger and probably bards as spellcasting threats. Two other AI issues are with Kaedrin’s spells. Blessed aim should be checking for ranged weapons being equipped. Energy weapon should only be cast once for one energy type. I will make changes for all of these issues for the next release.

At least for this battle, using spells is much more effective than going melee for the favored soul. I ran tests with limiting offensive spellcasting the PC usually lost the battle. The battle is challenging so the offensive spells would get used unless spellcasting is completely turned off.

2 Likes
InitializeBasicTargetInfo() in 'hench_i0_target'

while (TRUE)
{
    // iterate over 'ogClosestSeenEnemy'
    ogClosestSeenEnemy = GetNearestCreature(PERCEPTION_SEEN);

    if (bHasTrueSight && (GetCreaturePosEffects(ogClosestSeenEnemy) & HENCH_EFFECT_TYPE_ETHEREAL))
    {
        SetNotSeenOrHeardEnemy(ogClosestSeenEnemy);
        continue;
    }
}

while (TRUE)
{
    // iterate over 'ogClosestHeardEnemy'
    ogClosestHeardEnemy = GetNearestCreature(PERCEPTION_HEARD_AND_NOT_SEEN);

    if (bHasTrueSight && (GetCreaturePosEffects(ogClosestHeardEnemy) & HENCH_EFFECT_TYPE_ETHEREAL))
    {
        SetNotSeenOrHeardEnemy(ogClosestSeenEnemy); <-- should that be 'ogClosestHeardEnemy'
        continue;
    }
}

is ok? The second loop looks like it’s using the creature from the first while(TRUE) loop for SetNotSeenOrHeardEnemy()

This is a bug, I just corrected the script.

I have finished the fixes from demoix’s saved game. Bard fascinate is broken in the game - the mesmerize effect will not apply with the break on nearby combat flag set. I can’t find a good workaround for nearby combat checking - once in combat GetIsInCombat and other checks remain set after being mesmerized. The other spells that use EffectMesmerize work as designed.

I plan on getting a new release together with the current changes after some testing.

1 Like
HenchDecrementSpontaneousSpell() in 'hench_i0_itemsp'

for (talentCategory = TALENT_CATEGORY_CANTRIP; talentCategory--; talentCategory >= 0)
{
    // run spelllevel tests against GetCreatureTalentBest();
}

->

for (talentCategory = TALENT_CATEGORY_CANTRIP; talentCategory >= 0; talentCategory--)

?

 
also, Categories.2da #0 is “****” invalid … (but, not totally sure what’s going on as usual)

I will make the change but the bug just happens to work right, 0 is the last talent category searched.

Spells marked as **** in the spells 2da can be found using talent category zero. This includes some utility spells and some uncategorized spells. Talent category zero picks up a lot of skill and feat talents that are not useful. Things would work better if the spells 2da was changed to use existing or new talent categories but that would conflict with other custom content.

1 Like
// pre
// I am a familiar or animal companion, flee currently disabled.
// post
// I am a familiar or animal companion check fleeing

if (iAmFamiliar)
    case 4: SpeakStringByStrRef(230432); break; // I'll be back!

 
loL! nice to see you got that in… I had to check the .tlk before id believe that that string was actually in there :)

I just uploaded version 2.5: Companion and Monster AI 2.5 | The Neverwinter Vault

From the release notes:
New for version 2.5: Improve finding subspells when searching for spell talents. Add workaround for game spell resistance bug for items. Improve warlock spellcasting to better account for spell level in saves. Fix and improve knockdown and feint combat usage. Add support for flourish and impromptu sneak attack. Account for greater restoration full heal in AI. Fix issue with persistent aura duplicate cast when moving to target. Support for dragon spellcasting of clerical spells as arcane sorcerer. Fixes for spontaneous metamagic spellcasting being used with other spellcasting levels.

4 Likes

Precious update, thank you for your amazing work on updating AI! Does it compatible specifically only with Kaedrin’s PrC pack 1.41.4 or also could be used fine with latest 1.42.1?

The AI should work with the later versions. I do not have source code for the later versions and use it to configure the spellcasting and feat use for Kaedrin’s PrC pack in the AI. This means the AI will not use the newer class features when controlling your PC. This generally is not a problem since players who use the PrC pack want to use the class features themselves. I will probably go back and add support for some spells from 1.41.4 and earlier that have not yet been added to the AI.

2 Likes
HenchDoInitializeSpellInfo() in 'hench_o0_cacheinit'

    int subSpellIndex;
    do
    {
        int subSpellID = StringToInt(subRadSpellStr);
        SetLocalInt(oCacheObject, subSpellCachePrefix + IntToString(subSpellIndex++), subSpellID + 1);

        subRadSpellStr = Get2DAString(SPELLS_TABLE, "SubRadSpell" + IntToString(subSpellIndex + 1), spellID);
    }
    while ((subSpellIndex <= 5) && (GetStringLength(subRadSpellStr) > 0));

 
subSpellIndex starts at 0 and can go to 5 per the while() condition. Due to the quirky offsets against the iterator may i suggest ->

    int subSpellIndex;
    do
    {
        int subSpellID = StringToInt(subRadSpellStr);
        SetLocalInt(oCacheObject, subSpellCachePrefix + IntToString(subSpellIndex), subSpellID + 1);

        if (++subSpellIndex == 5)
            break;

        subRadSpellStr = Get2DAString(SPELLS_TABLE, "SubRadSpell" + IntToString(subSpellIndex + 1), spellID);
    }
    while (GetStringLength(subRadSpellStr) > 0);

 
Or simply rely, perhaps, on GetStringLength() for “SubRadSpell6” (column doesn’t exist) to return an empty string …

because even at 4 it’s going to iterate to 5, then +1 and try to get “SubRadSpell6” …

 
/ hope this computes

 
man you did some voodoo with those new SpontSpellcasting routines …

I have tested the new version 2.5 I and can’t find the word how happy I’m as the new improvements feel significant. Every feat, spell and abilities are being used by AI as it supposed to be. Feel like playing a new expansion for NWN2. So far I have fully tested OC and MOTB and I didn’t notice serious bugs. There are few observations I have noticed as per 2.5 version:

-Bug: AI enemy(not companions) using items infinitely even if the item has charge limit. Example: Ring of Nine Lives has 9 charges as 1charge/use but the enemy AI using this item more than 9 times. (Not sure if it is related to AI problem)
-Suggestion: AI summons to have ‘‘Guard distance: far’’, ‘‘Defend master: off’’. I have noticed once AI encounter the enemy they likely cast first front tank summons but once summon is summoned they not attacking the enemy on the sight which is a bad thing as the idea is to summon the summon to get front line defence so caster could win more time. Because the new summons settings are now Guard distance: default and Defend master is ON that means the new summons just coming to their masters and they even disappear as their time limit is gone even before attacks the enemy. Switching to Defend master off at least summons could do some damage to the enemy before they disappear especially on low-level characters.
-Bug/Suggestion: AI who has Ethereal Jaunt or similar spells likely go to Ethereal first and then buff themselves, but I have noticed they cast some harmful buff spells before they fully buff so in the result they lose Ethereal effect. Example: Battletide or Prayer is being cast on them selfs in the middle or buffing while there are other spells that could be cast to buff but Battletide and/or Prayer effects enemy with -2 penalty effects so AI loses Ethereal before they fully buff them selfs.
-Suggestion: On effect such as blind or deaf AI wandering around the same like dazed or charmed. At least in this state they could use buff them selfs if they have some spells or options, they could use this bad situation at least do something better for themselves but AI just walking around being blind or deaf. They not even healing even hurts and has spells/potions.
-Suggestion: Similar to above but AI could cast buffing themselves if the enemy goes to Ethereal state or become invisible to him. Currently, they do nothing and waiting for the enemy to become visible again.
-Bug: Silenced AI characters both enemy and companions do nothing but just walking around when silenced. Even melee non-caster characters do not attack once they got silenced. Feels like they act like blind/dazed instead.

4 Likes

Tony,

HenchCheckCureCondition() in 'hench_i0_heal'

if (bFullHeal)
{
	int iCurrent = GetLocalInt(oFriend, sHealingCurrentInfo);
	if (iCurrent != iHealingNotNeeded)
	{
		int iBase = GetMaxHitPoints(oFriend);
		int iHealAmount = iBase - iCurrent;
		if (iHealAmount >= (iBase / giHealingDivisor))
		{
			float curTargetWeight;
			if (gbDisableNonHealorCure || bIsSelf)
			{
				curTargetWeight = gfHealSelfWeightAdjustment;
			}
			else
			{
				curTargetWeight = gfHealOthersWeightAdjustment;
			}

			curTargetWeight *= (1.0 - (IntToFloat(iCurrent) / IntToFloat(iBase)));
			if (curTargetWeight > curEffectWeight)
			{
				curEffectWeight = curTargetWeight;
			}

			bIsSelf = TRUE;
		}
		else
		{
			if (bIsSelf && (iHealAmount >= (iBase / giHealingDivisor)))
			{
				SetLocalInt(OBJECT_SELF, HENCH_HEAL_SELF_STATE, HENCH_HEAL_SELF_WAIT); // <---- this never runs
			}
		}
	}
}

not sure if this matters but

looks like HENCH_HEAL_SELF_WAIT never runs since the condition (iHealAmount >= (iBase / giHealingDivisor)) has been consumed previously by if (iHealAmount >= (iBase / giHealingDivisor))

 
safe to ignore?

Hi TonyK, I hope you are doing very well!

I just want to drop some more observations regarding your mod:

-Bug: Enemy AI doesn’t summon animal companions in fights. (Companion AI’s do)

-Bug: With a new global option ‘‘NPC’s Auto rest/heal’’ in non-combat I noticed that this applies even when enemies are still in the fight when one of the enemies turns invincible during the fight, another NPC can’t see him so this global option auto rests this NPC as he can’t see anything, while technically he is still in the fight against the invincible enemy. So whenever in the middle of the fight 1vs1 someone goes invincible another gets auto rest.

-Suggestion: Disable intelligence (AI smartness) penalty for low INT NPC’s. The idea is good on paper as low INT orcs are supposed to be dumb, but please consider that sorcerers also have low INT scores and don’t need it because their main attribute is CHARISMA.

(RULE 7: AI is scaled based on the creature’s intelligence. Very low intelligence creatures only attack closest target, high intelligence creatures find and exploit enemies’ weaknesses. The AI will not cast inappropriate spells against a target that is immune to them, including elemental immunities like fire.)

And because of that they also suffer and not getting most of this mod which I believe is not fair because sorcerers are a masterpiece of magicians. If you could implant this option as global ON/OFF would be fantastic!

And one more thing if you are still active may I ask if you have future plans on updating your AI for NWN:EE aswell? You are sir genius creating and enhancing AI’s and community really appreciate this! Please if you need any support on Patreon or somewhere else just gimme a note I’m more than happy heavily support such projects! :slightly_smiling_face:

3 Likes

Can you provide the details of the fight you are talking about (module, act, etc.) or DM me a saved game to download that happens just before this issue?

I will look at some of the other issues you brought up. Some of them I have a good idea what is happening. For the rest, I may need more information or saved games to reproduce.

I am not currently planning of doing a new NWN release. I have investigated this, but it is a question of time, not money. It would take several weeks to convert over the NWN2 system, account for game and engine differences, and support new features like using items with the new functions. Also, the player base is now much smaller so getting enough testing by the community would be an issue.

1 Like

I have investigated this behaviour again and I got mixed results.
-Sometimes enemy/companion AI buffs once and/or more than once or wander around with no care while silenced (they could buff or heal from potions if available).
-Sometimes enemy/companion AI buffs once and/or more than once or wander around with no care while blinded/deafened (they could buff or heal from spells or potions if available).
SUGGESTION regarding the above: If they do buff themselves they should prevent buffing with sort duration buffs or in the best scenario they could calculate how long deaf/blind/silence or other negative effect remains. If the enemy is strong CL and casts (duration Blind/Deaf 6 sec * Caster Level) that means the target will have a negative effect quite long so not worth buffing with a short duration buff as it will expire before deaf/blind/silence expire.

I managed to make a workaround. I have edited feat.2da file and look for Familiar and AnimalCompanion rows. And edited their IsActive, IsPersistent, Instant rows to 1. As a result, every NPC who has Druid, Ranger, Wizard, Sorcerer has their Animal Companions and Familiars respectively in the world with them summoned.

I’m playing as DM client and watching AI fights. This save has been played at Battle of the Builds module with several mods by order 1. NWN2 Fixes 2. KaedPRCPack_v1.41.4 3. Spell_improvements_version_6.06 4. Companion and Monster AI 2.5. Where latest mod overrides others if necessary.

I made a video of AI behaviour with an explanation:
Problem accruing once one of the AI1 become Invincible/Ethereal/ or in any form while other AI2 can’t see AI1. Because AI2 can’t see anything it thinks there are no threats around so AUTO REST gets triggered for AI2. As result AI2 loses all buffs/negative effects plus gets full heal while it is still technically in the fight and the enemy (AI1) is a few feet away hiding in invincible mode. Once AI1 becomes visible again and strikes AI2, AI2 has to buff again in the middle of the fight. To achieve the best result AI2 tries to become Ethereal or invincible and buff in safe mode being invincible. So as result now AI1 thinks there are no threats around and the battle is over and gets AUTO REST and loses all buffs like AI2 before. It goes forever because once rest is triggered they also get all spells available again. Example1: 0:58 - AI1 (left side) uses Greater invisibility so AI2 (right side) can’t see anything and on 1:07 gets AUTO REST and loses all buffs. Example2: 1:55 AI2 (right side) uses Greater invincibility so AI1 (left side) 1:59 gets AUTO REST as thinks there is no battle and loses all buffs.

SUGGESTION: 1. AI to not get AUTO REST while technically they are in the fight. 2. Once they notice that an enemy goes Invincible/Ethereal and no other enemies around - do buffing as well or use potions to heal/buff but not stand and do nothing

Video:
https://www.youtube.com/watch?v=q28MPKQ8Ltk