//////////////////////////////////////////////////////////////////////////////// // ai_header - shared functions used in computer controlled team AI // By Deva Bryson Winblood. 04/13/2004 //////////////////////////////////////////////////////////////////////////////// int MAX_AI_UNITS = 30; int AI_GUARD = 2; int AI_FOLLOW = 5; int AI_GUARD_LAIR = 11; int AI_HEAL = 9; int AI_RAID = 17; int AI_RAID_ATTACK = 1; int AI_RAID_GOLD = 3; int AI_RAID_MANA = 2; ////////////////////////////// // PROTOTYPES ////////////////////////////// // returns the starting waypoint where players and leaders spawn object fnAIGetLairStart(string sID); // returns the object that the taxes are stored in for this team object fnAIGetLairChest(string sID); // returns how many units currently have 30 max for AI controlled team int fnAICountMembers(string sID); // returns a unit that matches the sTag type. If bNotBusy is set to // TRUE it will only return 1 that is not on a RAID, GUARD, or GUARD LAIR object fnAIGetMemberByType(string sID,string sTag,int bNotBusy=FALSE); // returns a unit that is not on RAID, GUARD, or GUARD LAIR // if bIncludeGuardLair is set to TRUE then it will return them if they // are doing Guard Lair also. object fnAIGetNonBusyMember(string sID,int bIncludeGuardLair=FALSE); // This returns how many of the sTag unit are currently under this AI Team // Leaders control. int fnAICountMemberType(string sID,string sTag); // This AI works with 30 units. This will return a # to an unaffiliated // number that can be used to create a new unit. int fnAIGetEmptyUnitNumber(string sID); // This will create sRes unit at location and assign it to unit // nNum 1-30. object fnAICreateUnit(string sID,string sRes,location lLoc,int nNum); // this returns a unit that is wounded down to nPercent or less of // their life. If bIncludeRaid is set to FALSE it will not return // any units on raiding missions. object fnAIGetWoundedUnit(string sID,int nPercent,int bIncludeRaid=FALSE); // returns the ID of the team that has the most trespass counts against this // team sID. string fnAIGetLargestTrespasser(string sID); // returns the ID of a team that has trespassed randomly chosen. string fnAIGetRandomTrespasser(string sID); // upgrade the unit oUnit to a new unit sRes with the same mission, // same nNum, etc. void fnAIUpgradeUnit(object oUnit,string sRes); // returns the team unit type # from the tag und25 would return 25 int fnAIGetUnitNumberFromTag(string sTag); // This function should be called once before any of the other AI // functions as it will populate the statistics and reduce the // amount of processing that would otherwise be required for some // of these. void fnAISetupStatistics(string sID); ////////////////////////////// // FUNCTIONS ////////////////////////////// object fnAIGetLairStart(string sID) { object oWP=GetWaypointByTag(sID+"_START"); return oWP; } // fnAIGetLairStart() object fnAIGetLairChest(string sID) { object oOb=GetObjectByTag(sID+"_CHEST"); return oOb; } // fnAIGetLairChest() int fnAICountMembers(string sID) { int nRet=0; object oMod=GetModule(); string sUnit; sUnit="nAdvAIUnitT"+sID; nRet=GetLocalInt(oMod,sUnit+"UC"); return nRet; } // fnAICountMembers() object fnAIGetMemberByType(string sID,string sTag,int bNotBusy=FALSE) { object oRet=OBJECT_INVALID; string sUnit; object oMod=GetModule(); object oUnit; int nState; int nL=1; while(nL<MAX_AI_UNITS+1&&oRet==OBJECT_INVALID) { // get member sUnit="oAdvAIUnit"+IntToString(nL); oUnit=GetLocalObject(oMod,sUnit); if (oUnit!=OBJECT_INVALID&&GetTag(oUnit)==sTag) { // busy if (bNotBusy==FALSE) return oRet; else { // see if busy nState=GetLocalInt(oUnit,"nMState"); if (nState!=AI_GUARD&&nState!=AI_FOLLOW&&nState!=AI_HEAL&&nState!=AI_GUARD_LAIR&&nState!=AI_RAID) return oRet; } // see if busy } // busy nL++; } // get member return oRet; } // fnAIAIGetMembersByType() object fnAIGetNonBusyMember(string sID,int bIncludeGuardLair=FALSE) { object oRet=OBJECT_INVALID; string sUnit; object oMod=GetModule(); object oUnit; int nState; int nL=1; while(nL<MAX_AI_UNITS+1&&oRet==OBJECT_INVALID) { // get member sUnit="oAdvAIUnit"+IntToString(nL); oUnit=GetLocalObject(oMod,sUnit); if (oUnit!=OBJECT_INVALID) { // unit nState=GetLocalInt(oUnit,"nMState"); if (nState!=AI_GUARD&&nState!=AI_FOLLOW&&nState!=AI_HEAL&&nState!=AI_RAID) { // possible candidate if (bIncludeGuardLair==FALSE) return oUnit; else if (nState!=AI_GUARD_LAIR) return oUnit; } // possible candidate } // unit nL++; } // get member return oRet; } // fnAIGetNonBusyMember() int fnAICountMemberType(string sID,string sTag) { int nRet=0; object oMod=GetModule(); string sUnit; object oUnit; nRet=fnAIGetUnitNumberFromTag(GetTag(oUnit)); sUnit="nAdvAIUnitC"+sID+IntToString(nRet); nRet=GetLocalInt(oMod,sUnit); return nRet; } // fnAICountMemberType() int fnAIGetEmptyUnitNumber(string sID) { int nRet=0; int nL=1; string sUnit; object oMod=GetModule(); while(nL<MAX_AI_UNITS+1&&nRet==0) { // find empty slot sUnit="oAdvAIUnit"+IntToString(nL); if (GetLocalObject(oMod,sUnit)==OBJECT_INVALID) nRet=nL; nL++; } // find empty slot return nRet; } // fnAIGetEmptyUnitNumber() object fnAICreateUnit(string sID,string sRes,location lLoc,int nNum) { object oRet=OBJECT_INVALID; object oMod=GetModule(); string sUnit="oAdvAIUnit"+sID+IntToString(nNum); object oCreate=CreateObject(OBJECT_TYPE_CREATURE,sRes,lLoc); //object oDM=GetFirstPC(); //while(oDM!=OBJECT_INVALID&&GetIsDM(oDM)!=TRUE) //{ // oDM=GetNextPC(); //} //if (GetIsDM(oDM)==TRUE) SendMessageToPC(oDM,GetName(oCreate)+" created in area "+GetName(GetArea(oCreate))+" RES="+sRes+" nNum="+IntToString(nNum)); SetLocalString(oCreate,"sTeamID",sID); SetLocalObject(oMod,sUnit,oCreate); SetLocalInt(oCreate,"nAIControlNum",nNum); oRet=oCreate; if (oCreate!=OBJECT_INVALID) PrintString(GetName(oCreate)+" spawned."); return oRet; } // fnAICreateUnit() object fnAIGetWoundedUnit(string sID,int nPercent,int bIncludeRaid=FALSE) { object oRet=OBJECT_INVALID; int nMax; int nCur; int nP; int nL=1; int nState; string sUnit; object oUnit; float fP; object oMod=GetModule(); while(nL<MAX_AI_UNITS+1&&oRet==OBJECT_INVALID) { // find wounded sUnit="oAdvAIUnit"+IntToString(nL); oUnit=GetLocalObject(oMod,sUnit); if (oUnit!=OBJECT_INVALID) { // !OI nMax=GetMaxHitPoints(oUnit); nCur=GetCurrentHitPoints(oUnit); if (nMax!=nCur) { // wounded if ((bIncludeRaid==FALSE&&GetLocalInt(oUnit,"nMState")!=AI_RAID)||bIncludeRaid==TRUE) { // okay to use fP=IntToFloat(nCur)/IntToFloat(nMax); fP=fP*100; nP=FloatToInt(fP); if (nP<=nPercent) return oUnit; } // okay to use } // wounded } // !OI nL++; } // find wounded return oRet; } // fnAIGetWoundedUnit() string fnAIGetLargestTrespasser(string sID) { string sRet="NA"; object oMod=GetModule(); string sTresPrefix="nAITrespass"+sID+"_"; int nCount=0; if (sID!="DWF"&&GetLocalInt(oMod,sTresPrefix+"DWF")>nCount) { nCount=GetLocalInt(oMod,sTresPrefix+"DWF"); sRet="DWF"; } if (sID!="UND"&&GetLocalInt(oMod,sTresPrefix+"UND")>nCount) { nCount=GetLocalInt(oMod,sTresPrefix+"UND"); sRet="UND"; } if (sID!="UNC"&&GetLocalInt(oMod,sTresPrefix+"UNC")>nCount) { nCount=GetLocalInt(oMod,sTresPrefix+"UNC"); sRet="UNC"; } if (sID!="SPID"&&GetLocalInt(oMod,sTresPrefix+"SPID")>nCount) { nCount=GetLocalInt(oMod,sTresPrefix+"SPID"); sRet="SPID"; } return sRet; } // fnAIGetLargestTrespasser() string fnAIGetRandomTrespasser(string sID) { string sRet="NA"; object oMod=GetModule(); int nCount=0; int nR; string sTresPrefix="nAITrespass"+sID+"_"; if (fnAIGetLargestTrespasser(sID)!="NA") { // there is a trespasser while(sRet=="NA") { // get trespasser nR=d4(); if (sID!="DWF"&&GetLocalInt(oMod,sTresPrefix+"DWF")>nCount&&nR==1) return "DWF"; else if (sID!="UND"&&GetLocalInt(oMod,sTresPrefix+"UND")>nCount&&nR==2) return "UND"; else if (sID!="UNC"&&GetLocalInt(oMod,sTresPrefix+"UNC")>nCount&&nR==3) return "UNC"; else if (sID!="SPID"&&GetLocalInt(oMod,sTresPrefix+"SPID")>nCount&&nR==4) return "SPID"; } // get trespasser } // there is a trespasser return sRet; } // fnAIGetRandomTrespasser() void fnAIUpgradeUnit(object oUnit,string sRes) { string sID=GetLocalString(oUnit,"sTeamID"); int nNum=GetLocalInt(oUnit,"nAIControlNum"); object oMod=GetModule(); string sUnit="oAdvAIUnit"+sID+IntToString(nNum); int nMState=GetLocalInt(oUnit,"nMState"); object oDest=GetLocalObject(oUnit,"oDestWP"); int nParm=GetLocalInt(oUnit,"nParm"); int nRun=GetLocalInt(oUnit,"nRun"); object oNew=CreateObject(OBJECT_TYPE_CREATURE,sRes,GetLocation(oUnit)); DestroyObject(oUnit); SetLocalString(oNew,"sTeamID",sID); SetLocalInt(oNew,"nAIControlNum",nNum); SetLocalInt(oNew,"nMState",nMState); SetLocalObject(oNew,"oDestWP",oDest); SetLocalInt(oNew,"nParm",nParm); SetLocalInt(oNew,"nRun",nRun); SetLocalObject(oMod,sUnit,oNew); } // fnAIUpgradeUnit() int fnAIGetUnitNumberFromTag(string sTag) { int nRet=0; string sParse=GetStringRight(sTag,2); if (StringToInt(GetStringLeft(sParse,1))==0) sParse=GetStringRight(sTag,1); nRet=StringToInt(sParse); return nRet; } // fnAIGetUnitNumberFromTag() void fnAISetupStatistics(string sID) { object oMod=GetModule(); int nL=0; int nS; string sUnit; object oUnit; int nUC=0; int nD=0; int nG=0; int nO=0; // clear statistics while(nL<30) { // clear total sUnit="nAdvAIUnitC"+sID+IntToString(nL); DeleteLocalInt(oMod,sUnit); nL++; } // clear total sUnit="nAdvAIUnitT"+sID; DeleteLocalInt(oMod,sUnit+"D"); // defensive DeleteLocalInt(oMod,sUnit+"G"); // guard DeleteLocalInt(oMod,sUnit+"O"); // offensive // get new statistics nL=1; while(nL<MAX_AI_UNITS+1) { // look at each unit sUnit="oAdvAIUnit"+sID+IntToString(nL); oUnit=GetLocalObject(oMod,sUnit); if (oUnit!=OBJECT_INVALID) { // !OI nS=GetLocalInt(oUnit,"nMState"); nUC++; if (nS==AI_GUARD_LAIR||nS==AI_GUARD||nS==AI_HEAL) nD++; if (nS==AI_GUARD) nG++; if (nS==AI_RAID) nO++; nS=fnAIGetUnitNumberFromTag(GetTag(oUnit)); sUnit="nAdvAIUnitC"+sID+IntToString(nS); nS=GetLocalInt(oMod,sUnit); nS++; SetLocalInt(oMod,sUnit,nS); } // !OI nL++; } // look at each unit sUnit="nAdvAIUnitT"+sID; SetLocalInt(oMod,sUnit+"D",nD); SetLocalInt(oMod,sUnit+"G",nG); SetLocalInt(oMod,sUnit+"O",nO); SetLocalInt(oMod,sUnit+"UC",nUC); } // fnAISetupStatistics() //void main(){}