//////////////////////////////////////////////////////////////////////////////// // cai_stealth - Custom Combat AI - Stealth Mode // By Deva Bryson Winblood. 11/2004 //////////////////////////////////////////////////////////////////////////////// #include "cai_inc_hos" #include "nw_I0_generic" 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||nC==CLASS_TYPE_DIVINECHAMPION||nC==CLASS_TYPE_BLACKGUARD) nThis=nThis+3; nC=GetClassByPosition(2,oOb); if (nC==CLASS_TYPE_CLERIC||nC==CLASS_TYPE_PALADIN||nC==CLASS_TYPE_DIVINECHAMPION||nC==CLASS_TYPE_BLACKGUARD) nThis=nThis+3; nC=GetClassByPosition(3,oOb); if (nC==CLASS_TYPE_CLERIC||nC==CLASS_TYPE_PALADIN||nC==CLASS_TYPE_DIVINECHAMPION||nC==CLASS_TYPE_BLACKGUARD) nThis=nThis+3; } // see if target is a cleric if (caiGetIsArcane(oOb)) nThis=nThis+2; 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 int fnGetHasInvisSpellEffect(object oNPC) { // PURPOSE: See if NPC already has an invisibility spell int bRet=FALSE; if (GetHasSpellEffect(SPELL_CAMOFLAGE,oNPC)==TRUE) return TRUE; if (GetHasSpellEffect(SPELL_IMPROVED_INVISIBILITY,oNPC)==TRUE) return TRUE; if (GetHasSpellEffect(SPELL_INVISIBILITY,oNPC)==TRUE) return TRUE; if (GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE,oNPC)==TRUE) return TRUE; return bRet; } // fnGetHasInvisSpellEffect() void main() { object oMe=OBJECT_SELF; object oTarget=GetAttackTarget(); float fF; int nN; int nMyRace=GetRacialType(oMe); object oBest=fnGetBestTarget(nMyRace); int nWT=caiGetEquippedWeaponType(oMe,INVENTORY_SLOT_RIGHTHAND); int bTargetChanged=FALSE; if (oBest!=oTarget) { oTarget=oBest; bTargetChanged=TRUE; } fF=GetDistanceBetween(oTarget,oMe); if (fF>5.0) { // go into stealth mode SetActionMode(oMe,ACTION_MODE_STEALTH,TRUE); if (fnGetHasInvisSpellEffect(oMe)==FALSE) { // see if can cast an invis spell if (GetHasSpell(SPELL_IMPROVED_INVISIBILITY,oMe)>0) { // improved invis AssignCommand(oMe,ActionCastSpellAtObject(SPELL_IMPROVED_INVISIBILITY,oMe)); } // improved invis else if (GetHasSpell(SPELL_INVISIBILITY,oMe)>0) { // invis AssignCommand(oMe,ActionCastSpellAtObject(SPELL_INVISIBILITY,oMe)); } // invis else if (GetHasSpell(SPELL_INVISIBILITY_SPHERE,oMe)>0) { // invis sphere AssignCommand(oMe,ActionCastSpellAtObject(SPELL_INVISIBILITY_SPHERE,oMe)); } // invis sphere else if (GetHasSpell(SPELL_CAMOFLAGE,oMe)>0) { // camoflage AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CAMOFLAGE,oMe)); } // camoflage } // see if can cast an invis spell } // go into stealth mode else { // no stealth mode SetActionMode(oMe,ACTION_MODE_STEALTH,FALSE); } // no stealth mode if (GetIsObjectValid(oTarget)) { // target is valid if (nWT==CAI_WEAPON_NONE||nWT==CAI_WEAPON_RANGED) { // equip a weapon AssignCommand(oMe,ActionEquipMostDamagingMelee(oTarget)); } // equip a weapon if (GetHasFeat(FEAT_TWO_WEAPON_FIGHTING,oMe)==TRUE) { // check to see if have a second weapon nN=caiGetEquippedWeaponType(oMe,INVENTORY_SLOT_LEFTHAND); if (nWT==CAI_WEAPON_NONE||nWT==CAI_WEAPON_RANGED) { // equip AssignCommand(oMe,ActionEquipMostDamagingMelee(oTarget,TRUE)); } // equip } // check to see if have a second weapon DetermineCombatRound(oTarget); } // target is valid }