//////////////////////////////////////////////////////////////////////////////// // cai_summon - Custom Combat AI - Summon 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 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; if (nState==1) { // summon spell if (GetIsObjectValid(GetAssociate(ASSOCIATE_TYPE_SUMMONED,oMe,1))==FALSE) { // no summoned critters nN=caiGetAvailableSummonSpell(oTarget); if (nN!=0) { // summon AssignCommand(oMe,ActionCastSpellAtLocation(nN,GetLocation(oMe))); } // summon else { nState=2; } } // no summoned critters else { nState=2; } } // summon spell if (nState==2) { // defensive spells nN=caiGetAvailableDefensiveSpell(oMe,oMe); if (nN==0) nState=3; else { // cast this spell AssignCommand(oMe,ActionCastSpellAtObject(nN,oMe)); } // cast this spell } // defensive spells if (nState==3) { // combat spell nN=caiGetAvailableCombatSpell(oMe,oTarget); if (nN!=0) { // spell found AssignCommand(oMe,ActionCastSpellAtObject(nN,oTarget)); } // spell found else { // nState=4; } // } // combat spell if (nState==4) { // summon spell if (GetIsObjectValid(GetAssociate(ASSOCIATE_TYPE_SUMMONED,oMe,2))==FALSE) { // no summoned critters nN=caiGetAvailableSummonSpell(oTarget); if (nN!=0) { // summon AssignCommand(oMe,ActionCastSpellAtLocation(nN,GetLocation(oMe))); } // summon else { DetermineCombatRound(oTarget); } } // no summoned critters } // summon spell } // 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 }