HoS_PRC8/_mod/_module/nss/cai_support.nss
Jaysyn904 04165202c0 Initial upload
Initial upload
2024-11-25 19:36:07 -05:00

260 lines
9.2 KiB
Plaintext

////////////////////////////////////////////////////////////////////////////////
// cai_Support - Custom Combat AI - Support Mode
// By Deva Bryson Winblood. 11/2004
////////////////////////////////////////////////////////////////////////////////
#include "cai_inc_hos"
#include "nw_I0_generic"
int fnClassIsSpellCaster(int nPos,object oNPC)
{ // tell me if this class is a spell caster
int nClass=GetClassByPosition(nPos,oNPC);
int bRet=FALSE;
switch(nClass)
{
case CLASS_TYPE_ARCANE_ARCHER:
case CLASS_TYPE_BARD:
case CLASS_TYPE_CLERIC:
case CLASS_TYPE_DRUID:
case CLASS_TYPE_FEY:
case CLASS_TYPE_DRAGONDISCIPLE:
case CLASS_TYPE_PALADIN:
case CLASS_TYPE_PALEMASTER:
case CLASS_TYPE_RANGER:
case CLASS_TYPE_SHADOWDANCER:
case CLASS_TYPE_SHIFTER:
case CLASS_TYPE_SORCERER:
case CLASS_TYPE_WIZARD: { bRet=TRUE; break; }
default: { break; }
}
return bRet;
} // fnClassIsSpellCaster()
object fnGetBestTarget(int nRace)
{ // tell me who my best target is at the moment
object oRet=OBJECT_INVALID;
int nN;
float fD;
int nVal;
object oOb;
int nThis;
int nC;
nN=1;
oOb=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,nN,CREATURE_TYPE_IS_ALIVE,TRUE,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
fD=GetDistanceBetween(oOb,OBJECT_SELF);
while(oOb!=OBJECT_INVALID&&fD<30.0)
{ // check all nearby targets
nThis=0;
nN++;
if (fD<20.0) nThis++;
if (fD<15.0) nThis++;
if (fD<10.0) nThis++;
if (fD<8.0) nThis++;
if (fD<5.0) nThis++;
fD=IntToFloat(GetCurrentHitPoints(oOb))/IntToFloat(GetMaxHitPoints(oOb));
if (fD<0.51) nThis++;
if (fD<0.31) nThis++;
if (fD<0.11) nThis++;
if (nRace==RACIAL_TYPE_UNDEAD)
{ // see if target is a cleric
nC=GetClassByPosition(1,oOb);
if (nC==CLASS_TYPE_CLERIC||nC==CLASS_TYPE_PALADIN) nThis=nThis+3;
nC=GetClassByPosition(2,oOb);
if (nC==CLASS_TYPE_CLERIC||nC==CLASS_TYPE_PALADIN) nThis=nThis+3;
nC=GetClassByPosition(3,oOb);
if (nC==CLASS_TYPE_CLERIC||nC==CLASS_TYPE_PALADIN) nThis=nThis+3;
} // see if target is a cleric
if (fnClassIsSpellCaster(1,oOb)) nThis++;
if (fnClassIsSpellCaster(2,oOb)) nThis++;
if (fnClassIsSpellCaster(3,oOb)) nThis++;
if (nThis>nVal)
{ // new best target
oRet=oOb;
nVal=nThis;
} // new best target
oOb=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,nN,CREATURE_TYPE_IS_ALIVE,TRUE,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
fD=GetDistanceBetween(oOb,OBJECT_SELF);
} // check all nearby targets
return oRet;
} // tell me who my best target is at the moment
void main()
{
object oMe=OBJECT_SELF;
object oTarget=GetAttackTarget();
float fF;
int nN;
int bMUST=FALSE;
int nMyRace=GetRacialType(oMe);
object oBest=fnGetBestTarget(nMyRace);
int bTargetChanged=FALSE;
int nState=GetLocalInt(oMe,"nCAIState");
if (oBest!=oTarget)
{
oTarget=oBest;
bTargetChanged=TRUE;
}
if (GetIsObjectValid(oTarget))
{ // target is valid
nState++;
if (nState>4) nState=1;
oBest=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,oMe,1,CREATURE_TYPE_IS_ALIVE,TRUE,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
if (GetIsObjectValid(oBest))
{ // there are enemies
if (GetDistanceBetween(oMe,oBest)<5.1)
{ // enemy too close
DetermineCombatRound(oBest);
} // enemy too close
else
{ // not close
oBest=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND,oMe,1,CREATURE_TYPE_IS_ALIVE,TRUE);
if (GetIsObjectValid(oBest))
{ // there are friends
if (GetDistanceBetween(oMe,oBest)<10.1)
{ // friends are close
nN=1;
oBest=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND,oMe,d6(),CREATURE_TYPE_IS_ALIVE,TRUE);
while((GetIsObjectValid(oBest)==FALSE||(GetDistanceBetween(oBest,oMe)<10.1&&GetDistanceBetween(oBest,oMe)!=0.0))&&nN<4)
{ // find friend
nN++;
oBest=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND,oMe,d6(),CREATURE_TYPE_IS_ALIVE,TRUE);
} // find friend
if (GetIsObjectValid(oBest)==FALSE) oBest=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND,oMe,1,CREATURE_TYPE_IS_ALIVE,TRUE);
if (GetIsObjectValid(oBest))
{ // friend to help found
nN=GetMaxHitPoints(oBest)-GetCurrentHitPoints(oBest);
if ((nN>0||GetIsDead(oBest))&&nState!=4)
{ // healing needed
if (GetIsPC(oBest)) nN=caiGetAvailableHealPC(oMe,oBest);
else if (GetIsDead(oBest)==FALSE) {
nN=caiGetAvailableHeal(oMe,nN); }
if (nN!=0)
{ // heal
AssignCommand(oMe,ActionCastSpellAtObject(nN,oBest));
} // heal
else
{ // combat
DetermineCombatRound(oTarget);
} // combat
} // healing needed
else if (GetMaxHitPoints(oMe)-GetCurrentHitPoints(oMe)>0)
{ // heal self
bMUST=FALSE;
if ((IntToFloat(GetCurrentHitPoints(oMe))/IntToFloat(GetMaxHitPoints(oMe)))<0.51) bMUST=TRUE;
nN=caiGetAvailableHeal(oMe,nN,bMUST);
if (nN!=0)
{ // heal self
AssignCommand(oMe,ActionCastSpellAtObject(nN,oBest));
} // heal self
else
{ // combat
DetermineCombatRound(oTarget);
} // combat
} // heal self
else if (nState!=4)
{ // defense, buff
if (nState==1)
{ // defense
nN=caiGetAvailableDefensiveSpell(oMe,oBest);
if (nN!=0)
{ // spell
AssignCommand(oMe,ActionCastSpellAtObject(nN,oBest));
} // spell
else
{ // combat
DetermineCombatRound(oTarget);
} // combat
} // defense
else
{ // buff
nN=caiGetAvailableBuff(oMe,oBest);
if (nN!=0)
{ // spell
AssignCommand(oMe,ActionCastSpellAtObject(nN,oBest));
} // spell
else
{ // combat
DetermineCombatRound(oTarget);
} // combat
} // buff
} // defense, buff
else
{ // combat
DetermineCombatRound(oTarget);
} // combat
} // friend to help found
} // friends are close
else
{ // I am alone
if (nState==1)
{ // defensive spell
nN=caiGetAvailableDefensiveSpell(oMe,oMe);
if (nN!=0)
{ // spell
AssignCommand(oMe,ActionCastSpellAtObject(nN,oMe));
} // spell
else
{ // combat
DetermineCombatRound(oMe);
} // combat
} // defensive spell
else if (nState==2||nState==4)
{ // combat
DetermineCombatRound(oMe);
} // combat
else if (nState==3)
{ // buff spell
nN=caiGetAvailableBuff(oMe,oMe);
if (nN!=0)
{ // spell
AssignCommand(oMe,ActionCastSpellAtObject(nN,oMe));
} // spell
else
{ // combat
DetermineCombatRound(oMe);
} // combat
} // buff spell
} // I am alone
} // there are friends
else
{ // I am alone
if (nState==1)
{ // defensive spell
nN=caiGetAvailableDefensiveSpell(oMe,oMe);
if (nN!=0)
{ // spell
AssignCommand(oMe,ActionCastSpellAtObject(nN,oMe));
} // spell
else
{ // combat
DetermineCombatRound(oMe);
} // combat
} // defensive spell
else if (nState==2||nState==4)
{ // combat
DetermineCombatRound(oMe);
} // combat
else if (nState==3)
{ // buff spell
nN=caiGetAvailableBuff(oMe,oMe);
if (nN!=0)
{ // spell
AssignCommand(oMe,ActionCastSpellAtObject(nN,oMe));
} // spell
else
{ // combat
DetermineCombatRound(oMe);
} // combat
} // buff spell
} // I am alone
} // not close
} // there are enemies
} // target is valid
// check need to heal self and remove negative spells
// set up sentinel for resting
if (GetLocalInt(oMe,"bCAIRESTSENTINEL")!=TRUE)
{ // trigger the sentinel
SetLocalInt(oMe,"bCAIRESTSENTINEL",TRUE);
caiRestSentinel(oMe);
} // trigger the sentinel
}