Scripting a (good) AI is one of the hardest things to do. There is a few projects in the Vault that do this, but they are full packages which may not do what you want (or do too much other stuff). But do check them out.
BW did let us hook into DetermineCombatRound
, but of course they turned it into a binary choice: either you handle whole combat yourself or you let vanilla handle whole combat. They didn’t provide a “do something yourself first but let vanilla finish it” third option.
Putting Divine Might to offensive talent category indeed causes the NPC to deadlock. However I made a quick and dirty hack allowing injecting this feat (or any feat really) into the vanilla DCR pipeline. This was actually fun (and it works).
Save this script as nwsh_dcr - this is my DCR hack library
/*
CUSTOM COMBAT OVERRIDE FOR VANILLA DETERMINE COMBAT ROUND
Allows vanilla AI to be called from custom AI
By NWShacker, 2021-01-09
Based on nw_i0_generic
*/
#include "nw_i0_generic"
#include "x2_inc_switches"
// wrapper for SetCreatureOverrideAIScript
void NWSH_SetCreatureOverrideAIScript(string sScript, object oCreature=OBJECT_SELF);
void NWSH_SetCreatureOverrideAIScript(string sScript, object oCreature=OBJECT_SELF)
{
SetCreatureOverrideAIScript(oCreature, sScript);
}
// initializes combat round override - MUST be called first
// * returns TRUE - can proceed with override script
// * returns FALSE - do not proceed with override script
int NWSH_DetermineCombatRoundInit();
int NWSH_DetermineCombatRoundInit()
{
if(__InCombatRound() || GetAssociateState(NW_ASC_IS_BUSY))
{
SetCreatureOverrideAIScriptFinished();
return FALSE;
}
__TurnCombatRoundOn(TRUE);
return TRUE;
}
// validates current attack target (passed to DetermineCombatRound())
// or obtains new attack target (nearest hostile creature)
object NWSH_DetermineCombatRoundTarget();
object NWSH_DetermineCombatRoundTarget()
{
object oIntruder = GetCreatureOverrideAIScriptTarget();
if(BashDoorCheck(oIntruder)) return OBJECT_INVALID;
if(bkEvaluationSanityCheck(oIntruder, 0.0)) return OBJECT_INVALID;
if(!GetIsObjectValid(oIntruder))
{
oIntruder = bkAcquireTarget();
}
return oIntruder;
}
// tries vanilla AI tactics against oIntruder
// DO NOT call this function directly
void NWSH_DetermineCombatRoundTactics(object oIntruder=OBJECT_INVALID)
{
if(TalentPersistentAbilities() || chooseTactics(oIntruder) == 99)
{
__TurnCombatRoundOn(FALSE);
}
else
{
DeleteLocalObject(OBJECT_SELF, "NW_GENERIC_LAST_ATTACK_TARGET");
ClearActions(CLEAR_NW_I0_GENERIC_658);
__TurnCombatRoundOn(FALSE);
WalkWayPoints();
}
}
// finishes combat round override - MUST be called last
// tries vanilla AI tactics against oIntruder (as action if iAsAction is TRUE)
void NWSH_DetermineCombatRoundExit(object oIntruder=OBJECT_INVALID, int iAsAction=FALSE);
void NWSH_DetermineCombatRoundExit(object oIntruder=OBJECT_INVALID, int iAsAction=FALSE)
{
if(iAsAction)
{
ActionDoCommand(NWSH_DetermineCombatRoundTactics(oIntruder));
}
else
{
NWSH_DetermineCombatRoundTactics(oIntruder);
}
SetCreatureOverrideAIScriptFinished();
}
Save this script as your_custom_ai or something - this is the custom AI
#include "nwsh_dcr"
int NWSH_UseDivineMight()
{
if(GetHasFeat(FEAT_DIVINE_MIGHT) &&
GetHasFeat(FEAT_TURN_UNDEAD) &&
!GetHasFeatEffect(FEAT_DIVINE_MIGHT))
{
ClearAllActions();
ActionUseFeat(FEAT_DIVINE_MIGHT, OBJECT_SELF);
return TRUE;
}
return FALSE;
}
void main()
{
if(!NWSH_DetermineCombatRoundInit())
{
return;
}
object oIntruder = NWSH_DetermineCombatRoundTarget();
int iAction;
if(GetIsObjectValid(oIntruder))
{
if(100 * GetHitDice(oIntruder) / GetHitDice(OBJECT_SELF) >= 50)
{
iAction = NWSH_UseDivineMight();
}
}
NWSH_DetermineCombatRoundExit(oIntruder, iAction);
}
Save this script as anything - this turns on custom AI (call it first)
#include "nwsh_dcr"
void main()
{
object oYourNPC = GetObjectByTag("YOUR_NPC_TAG_HERE");
NWSH_SetCreatureOverrideAIScript("your_custom_ai", oYourNPC);
}
NPC will use Divine Might only against enemies with 50%+ of its hit dice.