//////////////////////////////////////////////////////////////////////////////// // ai_raid_v2 - Version 2.0 of the Raid command for units // By Deva Bryson Winblood. 03/05/2005 // Modified April 9th, 2009 //////////////////////////////////////////////////////////////////////////////// #include "rts_header" #include "rts_wp_header" #include "rts_h_moving" #include "nw_i0_generic" #include "consolidate_h" #include "antistuck_h" ////////////////////////////// // PROTOTYPES ////////////////////////////// object fnDetermineNearestPathType(object oMe); object fnDetermineNextPath(string sID,string sDID,int nMode,int nCurrent); /////////////////////////////////////////////////////////////////////////// MAIN void main() { object oMe=OBJECT_SELF; int nSState=GetLocalInt(oMe,"nSState"); object oDest=GetLocalObject(oMe,"oDest"); object oItem; string sDID=GetLocalString(oMe,"sTeamToRaid"); string sID=GetLocalString(oMe,"sTeamID"); object oDestA=GetWaypointByTag(sDID+"_START"); object oAlly=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_FRIEND,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN); object oEnemy=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN); object oFEnemy=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY); object oFPC=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oMe,1,CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC); int bConsolidationLeader=GetLocalInt(oMe,"bConsolidationLeader"); int nMode=GetLocalInt(oMe,"nRaidMode"); int nParm=GetLocalInt(oMe,"nParm"); object oMod=GetModule(); int nRun=GetLocalInt(oMe,"nRun"); object oNearestPathType; object oH; int bEnemy=FALSE; int nN; string sMsg; int nC; int bShouldDeconsolidate=FALSE; int nLight=GetLocalInt(oMod,GetTag(oMe)+"_light"); if (GetLocalInt(oMod,"bUnitConsolidationOn")) { // consolidation is on if (nSState==1||nSState>3) bShouldDeconsolidate=TRUE; if (!bShouldDeconsolidate) { // test for should be consolidated nN=GetShouldConsolidate(oMe); if (nN==FALSE) bShouldDeconsolidate=TRUE; } // test for should be consolidated if (bConsolidationLeader&&bShouldDeconsolidate) { // deconsolidate ConsolidateFreeLeader(oMe); } // deconsolidate else if (!bShouldDeconsolidate) { // consolidate sMsg=sID+"_HOLDING"; if (GetStringLength(sID)<3) sMsg="NEUTRAL_HOLDING"; Consolidate(oMe,sMsg,"sTeamToRaid",40.0); } // consolidate } // consolidation is on if (oEnemy!=OBJECT_INVALID&&GetStringLength(GetLocalString(oEnemy,"sTeamID"))>0) bEnemy=TRUE; if (!bEnemy) { // enemy not present if (nMode>0) oNearestPathType=fnDetermineNearestPathType(oMe); switch(nSState) { // main switch case 0: { // determine type of pathing want if (GetIsDay()||GetIsDawn()) { // day time nN=d4(); if (nN<3) SetLocalInt(oMe,"nRaidMode",2); else { SetLocalInt(oMe,"nRaidMode",1); } if (nLight>0) SetLocalInt(oMe,"nRaidMode",2); } // day time else { // night time nN=d4(); if (nN==1) SetLocalInt(oMe,"nRaidMode",2); else { SetLocalInt(oMe,"nRaidMode",1); } } // night time if (oNearestPathType!=OBJECT_INVALID) SetLocalInt(oMe,"nSState",2); else { SetLocalInt(oMe,"nSState",1); } break; } // determine type of pathing want case 1: { // return to the lair if (oNearestPathType!=OBJECT_INVALID) SetLocalInt(oMe,"nSState",2); else { // return to lair oDest=GetWaypointByTag(sID+"_START"); if (GetArea(oDest)!=GetArea(oMe)) { // need to move oDest=fnPathNextDestination(GetArea(oMe),sID,0); if (oDest!=OBJECT_INVALID) { // move fnMoveToDestinationB(oMe,oDest,3.0); } // move } // need to move else { SetLocalInt(oMe,"nSState",2); } } // return to lair break; } // return to the lair case 2: { // pick waypoint nN=StringToInt(GetStringRight(GetTag(oNearestPathType),1)); if (oNearestPathType==oDestA) { // arrived at enemy lair // nParm if (nParm==0) SetLocalInt(oMe,"nSState",5); // 0 = informative else if (nParm==1) SetLocalInt(oMe,"nSState",4); // 1 = attack else if (nParm==2) SetLocalInt(oMe,"nSState",7); // 2 = steal gold else if (nParm==3) SetLocalInt(oMe,"nSState",6); // 3 = steal mana } // arrived at enemy lair else { // need to do moving oDest=fnDetermineNextPath(sID,sDID,nMode,nN); if (oDest!=OBJECT_INVALID) { // path found SetLocalInt(oMe,"nSState",3); SetLocalObject(oMe,"oDest",oDest); } // path found else { // error AssignCommand(oMe,SpeakString("cannot find path "+sID+","+sDID+","+IntToString(nMode)+","+IntToString(nN))); } // error } // need to do moving break; } // pick waypoint case 3: { // move to waypoint if (GetArea(oMe)!=GetArea(oDest)||GetDistanceBetween(oMe,oDest)>6.0) { // move fnMoveToDestinationB(oMe,oDest,1.0); } // move else { // arrived SetLocalInt(oMe,"nSState",2); } // arrived break; } // move to waypoint case 4: { // raid attack DeleteLocalInt(oMe,"bDisguised"); // just in case disguised undead if (oEnemy==OBJECT_INVALID) { // check for ally to help if (oAlly!=OBJECT_INVALID) { // ally present if (GetMaxHitPoints(oAlly)>GetCurrentHitPoints(oAlly)) { // heal if (GetHasSpell(SPELL_CURE_MINOR_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_MINOR_WOUNDS,oAlly)); } // cast else if (GetHasSpell(SPELL_CURE_LIGHT_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_LIGHT_WOUNDS,oAlly)); } // cast else if (GetHasSpell(SPELL_CURE_MODERATE_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_MODERATE_WOUNDS,oAlly)); } // cast else if (GetHasSpell(SPELL_CURE_SERIOUS_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_SERIOUS_WOUNDS,oAlly)); } // cast else if (GetHasSpell(SPELL_CURE_CRITICAL_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_CRITICAL_WOUNDS,oAlly)); } // cast else if (GetHasSpell(SPELL_HEAL)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_HEAL,oAlly)); } // cast else if (GetHasSpell(SPELL_HEALING_CIRCLE)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_HEALING_CIRCLE,oAlly)); } // cast else { // seek enemies oH=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d100()); if (oH!=OBJECT_INVALID) AssignCommand(oMe,ASActionMoveToObject(oH,nRun,4.0)); } // seek enemies } // heal else if (GetMaxHitPoints(oMe)>GetCurrentHitPoints(oMe)) { // I am wounded if (GetHasSpell(SPELL_CURE_MINOR_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_MINOR_WOUNDS,oMe)); } // cast else if (GetHasSpell(SPELL_CURE_LIGHT_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_LIGHT_WOUNDS,oMe)); } // cast else if (GetHasSpell(SPELL_CURE_MODERATE_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_MODERATE_WOUNDS,oMe)); } // cast else if (GetHasSpell(SPELL_CURE_SERIOUS_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_SERIOUS_WOUNDS,oMe)); } // cast else if (GetHasSpell(SPELL_CURE_CRITICAL_WOUNDS)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_CURE_CRITICAL_WOUNDS,oMe)); } // cast else if (GetHasSpell(SPELL_HEAL)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_HEAL,oMe)); } // cast else if (GetHasSpell(SPELL_HEALING_CIRCLE)>0) { // cast AssignCommand(oMe,ActionCastSpellAtObject(SPELL_HEALING_CIRCLE,oMe)); } // cast else { // seek enemies oH=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d100()); if (oH!=OBJECT_INVALID) AssignCommand(oMe,ASActionMoveToObject(oH,nRun,4.0)); } // seek enemies } // I am wounded else { // seek enemies oH=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d100()); if (oH!=OBJECT_INVALID) AssignCommand(oMe,ASActionMoveToObject(oH,nRun,4.0)); } // seek enemies } // ally present } // check for ally to help else { // enemy present if (GetRacialType(oEnemy)==RACIAL_TYPE_UNDEAD) { // Turn undead if(GetHasFeat(FEAT_TURN_UNDEAD)==TRUE) { // try to turn undead AssignCommand(oMe,ActionUseFeat(FEAT_TURN_UNDEAD,oMe)); } // try to turn undead } // Turn Undead } // enemy present break; } // raid attack case 5: { // informative AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_LOOK_FAR,2.0,6.0)); sMsg="I made it to the "+GetName(GetArea(oMe))+" and looked at their units. This is what I noticed"; nC=1; oH=GetNearestObject(OBJECT_TYPE_CREATURE,oMe,nC); while (oH!=OBJECT_INVALID) { //!OI sMsg=sMsg+", "+GetName(oH); nC++; oH=GetNearestObject(OBJECT_TYPE_CREATURE,oMe,nC); } //!OI sMsg=sMsg+". I then left to try to make it back to our lair to report."; oItem=CreateItemOnObject("rtsa_message",oMe); oDest=GetLocalObject(oMod,"oTeamLead"+sID); SetLocalString(oItem,"sMsg",sMsg); SetLocalObject(oItem,"oDest",GetWaypointByTag(sID+"_START")); SetLocalString(oItem,"sTo",GetName(oDest)); SetLocalString(oItem,"sName",GetName(oMe)); SetLocalObject(oMe,"oMsg",oItem); SetLocalInt(oMe,"nSState",8); break; } // informative case 6: { // steal gold SetActionMode(oMe,ACTION_MODE_STEALTH,TRUE); oDest=GetObjectByTag(sDID+"_CHEST"); if (GetDistanceBetween(oDest,oMe)>4.0) { // move AssignCommand(oMe,ClearAllActions()); AssignCommand(oMe,ActionMoveToObject(oDest,TRUE,3.0)); } // move else { // steal gold AssignCommand(oMe,ClearAllActions()); AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,3.0)); oH=GetItemPossessedBy(oDest,"NW_IT_GOLD001"); if (GetIsObjectValid(oH)) { // give gold GiveGoldToCreature(oMe,GetItemStackSize(oH)); DestroyObject(oH); } // give gold SetLocalInt(oMe,"nSState",8); } // steal gold break; } // steal gold case 7: { // steal mana SetActionMode(oMe,ACTION_MODE_STEALTH,TRUE); oDest=GetWaypointByTag(sDID+"_VAULT"); if (oDest!=OBJECT_INVALID) { // mana vault found if (GetDistanceBetween(oDest,oMe)>3.0) { // move fnMoveToDestinationB(oMe,oDest,1.0); } // move else { // pick up mana oDest=GetNearestObjectByTag("StrongManaPool",oMe,1); if (oDest==OBJECT_INVALID) oDest=GetNearestObjectByTag("ManaPool",oMe,1); if (oDest==OBJECT_INVALID) oDest=GetNearestObjectByTag("MinorManaPool",oMe,1); if (oDest!=OBJECT_INVALID) { // steal mana string sMTag=GetTag(oDest); string sMRes="mana_crystal_1"; if (sMTag=="StrongManaPool") sMRes="mana_crystal_5"; else if (sMTag=="ManaPool") sMRes="mana_crystal_2"; CreateItemOnObject(sMRes,oMe,1); DestroyObject(oDest); SetLocalInt(oMe,"nSState",8); } // steal mana else { SetLocalInt(oMe,"nSState",8); } } // pick up mana } // mana vault found else { // not found SetLocalInt(oMe,"nParm",0); SetLocalInt(oMe,"nSState",8); } // not found break; } // steal mana case 8: { // return to lair oDest=GetWaypointByTag(sID+"_START"); if (GetArea(oDest)!=GetArea(oMe)) { // need to move oDest=fnPathNextDestination(GetArea(oMe),sID,0); if (oDest!=OBJECT_INVALID) { // move fnMoveToDestinationB(oMe,oDest,3.0); } // move } // need to move else { // arrived if (nParm==0) SetLocalInt(oMe,"nSState",11); else if (nParm==2) SetLocalInt(oMe,"nSState",10); else if (nParm==3) SetLocalInt(oMe,"nSState",9); else { DeleteLocalInt(oMe,"nSState"); } } // arrived break; } // return to lair case 9: { // go to mana vault oDest=GetWaypointByTag(sID+"_VAULT"); if (GetDistanceBetween(oMe,oDest)>2.0) { // move fnMoveToDestinationB(oMe,oDest,1.0); } // move else { // arrived SetLocalInt(oMe,"nSState",0); } // arrived break; } // go to mana vault case 10: { // give gold nN=GetGold(oMe); oDest=GetObjectByTag(sID+"_CHEST"); if (oDest!=OBJECT_INVALID) { // chest exists if (GetDistanceBetween(oMe,oDest)<3.0) { // deposit AssignCommand(oMe,ClearAllActions()); AssignCommand(oMe,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,3.0)); CreateItemOnObject("nw_it_gold001",oDest,nN); TakeGoldFromCreature(nN,oMe,TRUE); SetLocalInt(oMe,"nSState",0); } // deposit else { // move AssignCommand(oMe,ClearAllActions()); AssignCommand(oMe,ActionMoveToObject(oDest,TRUE,2.0)); } // move } // chest exists else { DeleteLocalInt(oMe,"nSState"); } break; } // give gold case 11: { // deliver message oDest=GetWaypointByTag(sID+"_START"); if (oDest!=OBJECT_INVALID) { // move if (GetDistanceBetween(oMe,oDest)>2.5) { // move fnMoveToDestinationB(oMe,oDest,1.0); } // move else { // drop item oItem=GetLocalObject(oMe,"oMsg"); if (GetItemPossessor(oItem)==oMe) AssignCommand(oMe,ActionPutDownItem(oItem)); else { DeleteLocalInt(oMe,"nSState"); DeleteLocalObject(oMe,"oMsg"); } } // drop item } // move else { DeleteLocalInt(oMe,"nSState"); } break; } // deliver message default: { DeleteLocalInt(oMe,"nSState"); break; } } // main switch } // enemy not present else { // enemy is present if (!GetIsInCombat(oMe))DetermineCombatRound(oEnemy); DeleteLocalInt(oMe,"nSState"); } // enemy is present } /////////////////////////////////////////////////////////////////////////// MAIN ////////////////////////// // FUNCTIONS ////////////////////////// object fnDetermineNearestPathType(object oMe) { // PURPOSE: To check the nearest waypoints object oRet=OBJECT_INVALID; string sID=GetLocalString(oMe,"sTeamID"); string sDID=GetLocalString(oMe,"sTeamToRaid"); int nMode=GetLocalInt(oMe,"nRaidMode"); string sMode="N"; if (nMode==2) sMode="S"; oRet=GetNearestObjectByTag(sDID+"_START",oMe); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_"+sDID+"_7"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_7"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_"+sDID+"_6"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_6"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_"+sDID+"_5"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_5"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_"+sDID+"_4"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_4"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_"+sDID+"_3"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_3"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_"+sDID+"_2"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_2"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_"+sDID+"_1"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_1"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_"+sDID+"_0"); if (oRet==OBJECT_INVALID) oRet=GetNearestObjectByTag(sID+"_RAID"+sMode+"_0"); return oRet; } // fnDetermineNearestPathType() object fnDetermineNextPath(string sID,string sDID,int nMode,int nCurrent) { // PURPOSE: return information about the next destination object oRet=OBJECT_INVALID; int nN=nCurrent+1; string sMode="N"; if (nMode==2) sMode="S"; oRet=GetWaypointByTag(sID+"_RAID"+sMode+"_"+sDID+"_"+IntToString(nN)); if (oRet==OBJECT_INVALID) oRet=GetWaypointByTag(sID+"_RAID"+sMode+"_"+IntToString(nN)); return oRet; } // fnDetermineNextPath()