Added PEPS AI. Updated module name. Set all henchmen to have a random race &/or class based name using a custom version of Markshire's Nomeclature scripts, as well as appearance. Set Constructs, Undead, Outsiders & Elementals to not require food or drink. Full compile.
106 lines
5.7 KiB
Plaintext
106 lines
5.7 KiB
Plaintext
/*////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Script Name: ai_a_ambusher
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
ai script for associates to ambush creatures by hiding or turning invisible.
|
|
OBJECT_SELF is the creature running the ai.
|
|
* This assumes we are not invisible since the ai_a_invisible script should fire if we are.
|
|
*/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Programmer: Philos
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#include "0i_actions"
|
|
void main()
|
|
{
|
|
object oCreature = OBJECT_SELF;
|
|
// Get the number of enemies that we are in melee combat with.
|
|
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
|
|
object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST);
|
|
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "19", GetName(oCreature) + " is using ambusher tactics: " +
|
|
" oNearestEnemy: " + GetName(oNearestEnemy) + " fDistance: " +
|
|
FloatToString(GetDistanceBetween(oNearestEnemy, oCreature), 0, 2));
|
|
if(GetDistanceBetween(oNearestEnemy, oCreature) > AI_RANGE_CLOSE)
|
|
{
|
|
// Has our master told us to not use magic?
|
|
if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC))
|
|
{
|
|
// If can turn invisible then we should probably do that!
|
|
if(ai_UseTalent(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature)) return;
|
|
if(ai_UseTalent(oCreature, SPELL_INVISIBILITY, oCreature)) return;
|
|
if(ai_UseTalent(oCreature, SPELL_INVISIBILITY_SPHERE, oCreature)) return;
|
|
if(ai_UseTalent(oCreature, SPELL_SANCTUARY, oCreature)) return;
|
|
if(ai_UseTalent(oCreature, SPELL_ETHEREALNESS, oCreature)) return; // Greater Sanctuary
|
|
if(ai_UseTalent(oCreature, SPELLABILITY_AS_IMPROVED_INVISIBLITY, oCreature)) return;
|
|
if(ai_UseTalent(oCreature, SPELLABILITY_AS_INVISIBILITY, oCreature)) return;
|
|
}
|
|
}
|
|
// Check the battle field to see if anyone see us?
|
|
int nEnemyIndex = ai_GetNearestIndexThatSeesUs(oCreature);
|
|
// If seen, can we try to hide now?
|
|
if(nEnemyIndex)
|
|
{
|
|
// Check for an attacker and can they see through invisibility?
|
|
object oAttacker = ai_GetEnemyAttackingMe(oCreature);
|
|
int bCanSeeInvisible;
|
|
if(oAttacker != OBJECT_INVALID)
|
|
{
|
|
bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_SEEINVISIBLE);
|
|
if(!bCanSeeInvisible) bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_TRUESEEING);
|
|
if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_5_FEET, oCreature);
|
|
if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_10_FEET, oCreature);
|
|
if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_60_FEET, oCreature);
|
|
}
|
|
if(!bCanSeeInvisible)
|
|
{
|
|
if(GetHasFeat(FEAT_HIDE_IN_PLAIN_SIGHT, oCreature))
|
|
{
|
|
if(!GetActionMode(oCreature, ACTION_MODE_STEALTH))
|
|
{
|
|
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "55", GetName(oCreature) + " is using hide in plain sight!");
|
|
ClearAllActions(TRUE);
|
|
SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE);
|
|
return;
|
|
}
|
|
}
|
|
// Does not have hide in plain sight.
|
|
else
|
|
{
|
|
string sEnemyIndex = IntToString(nEnemyIndex);
|
|
float fEnemyDistance = GetLocalFloat(oCreature, AI_ENEMY_RANGE + sEnemyIndex);
|
|
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "66", "fDistance: " + FloatToString(fEnemyDistance, 0, 2));
|
|
if(fEnemyDistance > 20.0)
|
|
{
|
|
int bTried = GetLocalInt(oCreature, AI_TRIED_TO_HIDE);
|
|
if(!bTried)
|
|
{
|
|
// Move away so we can hide.
|
|
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "73", GetName(oCreature) + " is trying to move away to hide!");
|
|
SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
|
|
object oEnemy = GetLocalObject(oCreature, AI_ENEMY + sEnemyIndex);
|
|
ActionMoveAwayFromObject(oEnemy, TRUE, AI_RANGE_BATTLEFIELD);
|
|
SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3);
|
|
return;
|
|
}
|
|
else SetLocalInt(oCreature, AI_TRIED_TO_HIDE, GetLocalInt(oCreature, AI_TRIED_TO_HIDE) - 1);
|
|
}
|
|
// We have been seen by an enemy near us so drop stealth.
|
|
else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
|
|
}
|
|
}
|
|
// The enemy can see through stealth so lets drop it.
|
|
else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
|
|
}
|
|
// We are not in stealth mode so and no one sees us so lets hide.
|
|
else if(!GetActionMode(oCreature, ACTION_MODE_STEALTH))
|
|
{
|
|
// Use any hiding talents we have
|
|
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "97", GetName(oCreature) + " is trying to hide!");
|
|
SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE);
|
|
SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3);
|
|
return;
|
|
}
|
|
// If we have givin up on stealth do our normal actions.
|
|
string sScript = GetLocalString(oCreature, AI_DEFAULT_SCRIPT);
|
|
if(sScript == "ai_a_ambusher" || sScript == "") sScript = "ai_a_default";
|
|
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "101", "Executing Script: " + sScript);
|
|
ExecuteScript(sScript, oCreature);
|
|
}
|