Amon_PRC8/_module/nss/x2_ai_mflayer.nss
Jaysyn904 c5cffc37af Initial Commit
Initial Commit [v1.01]
2025-04-03 19:00:46 -04:00

347 lines
8.2 KiB
Plaintext

//::///////////////////////////////////////////////
//:: Custom Mindflayer AI
//:: x2_ai_mflayer
//:: Copyright (c) 2003 Bioware Corp.
//:://////////////////////////////////////////////
/*
This is the Hordes of the Underdark campaign
Mini AI run on the mindflayer.
It does not use any spells assigned to the
mindflayer, if you want to make a custom mindflayer
you need to deactivate this AI by removing the
approriate variable from your beholder creature
in the toolset
*/
//:://////////////////////////////////////////////
//:: Created By: Georg Zoeller
//:: Created On: 2003-08-21
//:://////////////////////////////////////////////
#include "nw_i0_generic"
#include "x0_i0_spells"
#include "x2_inc_switches"
#include "x2_inc_toollib"
#include "prc_racial_const"
#include "hench_i0_generic"
const int X2_MINDFLAYER_TELEPORT_MAXUSES = 10;
int MFGetTargetConditionSucks(object oTarget)
{
// if polymorphed we do not suck
if (GetHasEffect(EFFECT_TYPE_POLYMORPH, oTarget) == TRUE)
{
return FALSE;
}
if (GetHasEffect(EFFECT_TYPE_STUNNED, oTarget) || GetHasEffect(EFFECT_TYPE_PARALYZE, oTarget)
|| GetHasEffect(VFX_DUR_PARALYZE_HOLD, oTarget) || GetHasEffect(VFX_DUR_PARALYZE_HOLD, oTarget) )
{
return TRUE;
}
else
{
// if dazed, try to brainsuck only 30% of the time)
if (GetHasEffect(EFFECT_TYPE_DAZED, oTarget) && (Random(100)<30) )
{
return TRUE;
}
return FALSE;
}
}
void MFlayerSuck(object oTarget)
{
if (GetDistanceBetween( OBJECT_SELF, oTarget ) < 1.5f)
{
ActionMoveAwayFromObject(oTarget, FALSE, 1.5f);
}
else
{
ActionMoveToObject( oTarget, TRUE, 1.5f);
}
ActionDoCommand(SetFacingPoint(GetPositionFromLocation(GetLocation(oTarget))));
ActionWait(0.5f);
ActionCastSpellAtObject(716, oTarget,METAMAGIC_ANY,TRUE,0,PROJECTILE_PATH_TYPE_DEFAULT);
}
int MFCheckCreature(object oTarget)
{
if (GetCreatureUseItems(oTarget) &&
!GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT, OBJECT_SELF) &&
!GetIsImmune(oTarget, IMMUNITY_TYPE_MIND_SPELLS, OBJECT_SELF) &&
!GetIsImmune(oTarget, IMMUNITY_TYPE_ABILITY_DECREASE, OBJECT_SELF))
{
// if the target is down below 10 hp and AC is below 23, we go into melee as well
if (GetCurrentHitPoints(oTarget) > 10 || GetAC(oTarget) >= 23)
{
if (MFGetTargetConditionSucks(oTarget))
{
__TurnCombatRoundOn(TRUE);
MFlayerSuck(oTarget);
__TurnCombatRoundOn(FALSE);
SetCreatureOverrideAIScriptFinished();
return TRUE;
}
}
}
return FALSE;
}
int MFlayerDoPsionics(object oTarget)
{
return TalentSpellAttack(oTarget);
}
void MFlayClearFleeState()
{
DeleteLocalInt(OBJECT_SELF,"X2_MFLAYER_AI_FLEEING");
}
void MFlayClearState()
{
if (GetCurrentAction(OBJECT_SELF) == ACTION_ATTACKOBJECT || GetCurrentAction(OBJECT_SELF) == ACTION_MOVETOPOINT )
{
ClearAllActions();
}
}
/*
int TryToTeleport(object oTargetFrom, int bCloseIn = FALSE)
{
int nTeleportCounter = GetLocalInt(OBJECT_SELF,"X2_MINDFLAYER_AI_TELECOUNT");
if (nTeleportCounter > X2_MINDFLAYER_TELEPORT_MAXUSES)
{
return FALSE;
}
else
{
nTeleportCounter ++;
SetLocalInt(OBJECT_SELF,"X2_MINDFLAYER_AI_TELECOUNT",nTeleportCounter);
}
object oExit;
if (bCloseIn)
{
oExit = GetNearestObjectByTag("X2_WP_MFLAYER_EXIT",oTargetFrom);
}
else
{
oExit = GetNearestObjectByTag("X2_WP_MFLAYER_EXIT");
}
if (!GetIsObjectValid(oExit))
{
return FALSE;
}
float fDist = GetDistanceBetween(oExit,oTargetFrom);
int bJump;
if (bCloseIn)
{
if ((fDist >= 8.0f) && (fDist <= 20.0f))
{
bJump = TRUE;
}
}
else
{
if ((fDist >= 10.0f) && (fDist <= 40.0f))
{
bJump = TRUE;
}
}
if (!bJump)
{
if (bCloseIn)
{
oExit = GetNearestObjectByTag("X2_WP_MFLAYER_EXIT",oTargetFrom,2);
}
else
{
oExit = GetNearestObjectByTag("X2_WP_MFLAYER_EXIT",OBJECT_SELF,2);
}
if (!GetIsObjectValid(oExit))
{
return FALSE;
}
else
{
fDist = GetDistanceBetween(oExit,oTargetFrom);
if (bCloseIn)
{
if ((fDist >= 6.0f) && (fDist <= 15.0f))
{
bJump = TRUE;
}
}
else
{
if ((fDist >= 8.0f) && (fDist <= 50.0f))
{
bJump = TRUE;
}
}
}
}
if (bJump)
{
if (!GetIsDead(OBJECT_SELF))
{
effect eAppear = EffectDisappearAppear(GetLocation(oExit)) ;
eAppear = ExtraordinaryEffect(eAppear);
object oSelf = OBJECT_SELF;
//effect eVis = EffectVisualEffect(VFX_IMP_UNSUMMON);
//ApplyEffectToObject(DURATION_TYPE_INSTANT,eVis,oSelf);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eAppear,oSelf,4.0f);
}
return TRUE;
}
else
{
return FALSE;
}
return TRUE;
}
*/
// 1 - Melee
// 2 - Suck
int GetMindFlayerTactics(object oTarget)
{
int nRet = FALSE;
// we go melee against petrified targets
if (GetHasEffect(EFFECT_TYPE_PETRIFY, oTarget) == TRUE)
{
nRet = 1;
}
else if ((GetIsPlayableRacialType(oTarget) && MFGetTargetConditionSucks(oTarget) || (GetSubRace(oTarget)== "Tiefling")|| GetRacialType(oTarget) == RACIAL_TYPE_TIEFLING))
{
nRet = 2;
}
// if the target is down below 10 hp and AC is below 23, we go into melee as well
else if ( GetCurrentHitPoints(oTarget) < 10 && GetAC(oTarget) < 23)
{
nRet = 1;
}
return nRet;
}
void main()
{
//The following two lines should not be touched
object oIntruder = GetCreatureOverrideAIScriptTarget();
ClearCreatureOverrideAIScriptTarget();
SetLocalInt(OBJECT_SELF, "HENCH_USE_MIND_BLAST", TRUE);
// ********************* Start of custom AI script ****************************
// Here you can write your own AI to run in place of DetermineCombatRound.
// The minimalistic approach would be something like
//
// TalentFlee(oTarget); // flee on any combat activity
/* if(GetAssociateState(NW_ASC_IS_BUSY))
{
return;
}
if (GetIsObjectValid(oIntruder) == FALSE)
oIntruder = bkAcquireTarget();
if(BashDoorCheck(oIntruder)) {return;}
// * BK: stop fighting if something bizarre that shouldn't happen, happens
if (bkEvaluationSanityCheck(oIntruder, GetFollowDistance()) == TRUE)
{
return;
}
if (GetIsObjectValid(oIntruder) == FALSE || GetIsDead(oIntruder))
{
return; // fall back to default AI because SetCreatureOverrideAIScriptFinished(); wasnt called t cal
} */
if (MFCheckCreature(oIntruder))
{
return;
}
object oCurTarget;
// location testTargetLoc;
int curLoopCount = 1;
oCurTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY,
OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN,
CREATURE_TYPE_IS_ALIVE, TRUE);
effect curEffect;
// testTargetLoc = GetLocation(OBJECT_SELF);
while (GetIsObjectValid(oCurTarget) && curLoopCount <= 10)
{
if (GetDistanceToObject(oCurTarget) > 15.0)
{
break;
}
if (MFCheckCreature(oCurTarget))
{
return;
}
curLoopCount ++;
oCurTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY,
OBJECT_SELF, curLoopCount, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN,
CREATURE_TYPE_IS_ALIVE, TRUE);
}
/*
int nTactics = GetMindFlayerTactics(oIntruder);
if (nTactics == 2)
{
__TurnCombatRoundOn(TRUE);
MFlayerSuck(oIntruder);
__TurnCombatRoundOn(FALSE);
SetCreatureOverrideAIScriptFinished();
}
else
{
return; // fall back to default AI because SetCreatureOverrideAIScriptFinished(); wasnt called t cal
}
*/
}