I went back to this problem when making an example script for another project. Since the work is already done, I’m leaving this here as an educational resource.
The issue I have is that BW’s
TalentHeal always goes for the best healing spell, which makes AI use i.e. Heal regardless of target (overkill, wasteful, you call it).
TRUE parameter just makes it heal any damage, not just <50%. It can however find the target itself - no need for
GetFirstObjectInShape (but it doesn’t honor LOS).
So, I made a smarter healer script that gradually tries to find the lowest spell level that should match the target.
GetTalent below does this magic.
CREATURE HEARTBEAT SCRIPT
Caller checks all seen, friendly and alive creatures (not undead)
and heals closest one with less than 50% of maximum HP.
const int TALENT_HEAL = TALENT_CATEGORY_BENEFICIAL_HEALING_TOUCH;
// Returns most economical talent in iCategory to be used by oSelf on oTarget.
// Most economical means one that is closest to oTarget's CR. If iBest is TRUE
// then this function returns talent at highest CR. If no talent is available
// in this category, an invalid talent will be returned.
talent GetTalent(int iCategory, object oTarget, int iBest=FALSE, object oSelf=OBJECT_SELF)
iCR = iBest ? TALENT_ANY : FloatToInt(GetChallengeRating(oTarget));
tTalent = GetCreatureTalentBest(iCategory, iCR++, oSelf);
while(!GetIsTalentValid(tTalent) && iCR <= TALENT_ANY);
// Proceed only when idle or walking.
// Start healing target scan with self.
oTarget = OBJECT_SELF;
// Check if target has less than 50% of its maximum HP and
// is not an undead (too late for healing in this case).
if(GetCurrentHitPoints(oTarget) * 2 < GetMaxHitPoints(oTarget)
&& GetRacialType(oTarget) != RACIAL_TYPE_UNDEAD)
// Obtain most economical healing talent for target.
tHeal = GetTalent(TALENT_HEAL, oTarget);
// Check if target can be healed (talent is valid).
ActionSpeakString("Healing " + GetName(oTarget) + ".");
// Return (if target cannot be healed then nobody can be).
// Get next target (nearest seen allied creature).
oTarget = GetNearestSeenFriend(OBJECT_SELF, iTarget++);
TALENT_ANY = 20, as defined in