/////////////////////////////////////////////////////////////////////////////////// // REAL TIME STRATEGY ADVENTURE - Kit // FILE: rtsa_p_garrison // NAME: Garrison Heartbeat script // SCRIPTED BY: Deva Bryson Winblood // DATE: 06/16/2003 // LAST MODIFIED: 03/07/2005 /////////////////////////////////////////////////////////////////////////////////// #include "rtsa_headerp" // Parser function header #include "antistuck_h" void fnMsgAllPlayers(string sMsg) { // PURPOSE: send a message to all players object oPC=GetFirstPC(); while(oPC!=OBJECT_INVALID) { // each player SendMessageToPC(oPC,sMsg); oPC=GetNextPC(); } // each player } // fnMsgAllPlayers() string fnBanter(int nLang,int nPhrase,int nSpeaker) { // return the proper phrase for language for phrase 1-5, speaker 1 or 2 string sRet=""; switch(nPhrase) { // phrase switch case 1: { // Stay Alert line switch(nLang) { // Language Switch case 1: { // Ruffian if (nSpeaker==2) sRet="Aye, they're out in force lately."; else sRet="Keep an eye out for the militia."; break; } // Ruffian case 2: { // Noble if (nSpeaker==2) sRet="Yes sir, sergeant."; else sRet="Stay sharp. There are ruffians about."; break; } // Noble case 3: { // Cant if (nSpeaker==2) sRet="I'm fly."; else sRet="If the lout ribald smokes you I'll razor your whistle!"; break; } // Cant case 4: { // Mercenary if (nSpeaker==2) sRet="The purse better be big for this one."; else sRet="Stay alert! This is what we're paid for."; break; } // Mercenary case 5: { // Monster1 if (nSpeaker==2) sRet="Just funny shape rock."; else sRet="Urk. I see elf!"; break; } // Monster1 case 6: { // Monster2 if (nSpeaker==2) sRet="That's more pleasant than what would probably happen."; else sRet="Stand fast. They will melt the skin from our bodies if anyone gets by."; break; } // Monster2 case 7: { // Pious if (nSpeaker==2) sRet="Blessings of the Lord of Light be upon us. Strike true!"; else sRet="I sense danger nearby."; break; } // Pious case 8: { // Nature if (nSpeaker==2) sRet="That was just a shadow cast by the clouds."; else sRet="Beware I saw an orc!"; break; } // Nature default: break; } // Language Switch break; } // Stay Alert line case 2: { // Hunger/Thirst Line switch(nLang) { // Language Switch case 1: { // Ruffian if (nSpeaker==2) sRet="A mug sounds good here, too."; else sRet="I could really do with a bit o' ale."; break; } // Ruffian case 2: { // Noble if (nSpeaker==2) sRet="I am having enough trouble doing my duty here. Keep quiet about food!"; else sRet="I can just imagine the lovely taste of food."; break; } // Noble case 3: { // Cant if (nSpeaker==2) sRet="You addled?"; else sRet="Gimme the cackle-farts and grunting peck."; break; } // Cant case 4: { // Mercenary if (nSpeaker==2) sRet="Let me guess. Trail bread and beans again?"; else sRet="Almost time to hit the mess for some grub."; break; } // Mercenary case 5: { // Monster1 if (nSpeaker==2) sRet="Gnaw da bones an eat da flesh!"; else sRet="Hunnnnnngry!"; break; } // Monster1 case 6: { // Monster2 if (nSpeaker==2) sRet="Nothing quite quenches the thirst like it."; else sRet="I have a thirst for fresh blood."; break; } // Monster2 case 7: { // Pious if (nSpeaker==2) sRet="Aaah, blessed respite."; else sRet="Almost time to feast and take a break."; break; } // Pious case 8: { // Nature if (nSpeaker==2) sRet="Nature's bounty is all around us, friend. Grab some berries off that bush there."; else sRet="I could use a bite to eat."; break; } // Nature default: break; } // Language Switch break; } // Hunger/Thirst Line case 3: { // Put Down/Dream/Light Chatter Line switch(nLang) { // Language Switch case 1: { // Ruffian if (nSpeaker==2) sRet="Don't you be eyeing my weapon. I don't mean no buggering from ye!"; else sRet="I be eyeing your weapon there. You be caring well for it I see."; break; } // Ruffian case 2: { // Noble if (nSpeaker==2) sRet="I did too. I wonder if it was a sign?"; else sRet="I had a bad dream last night."; break; } // Noble case 3: { // Cant if (nSpeaker==2) sRet="Nay!"; else sRet="You be cutty-eyeing my book?"; break; } // Cant case 4: { // Mercenary if (nSpeaker==2) sRet="Too bad you lost your cloak playing dice last night."; else sRet="Looks like rain coming."; break; } // Mercenary case 5: { // Monster1 if (nSpeaker==2) sRet="Rrrraagh! I kill you for that."; else sRet="*sniff* You smell like rose bush."; break; } // Monster1 case 6: { // Monster2 if (nSpeaker==2) sRet="Haha that was a good one! Mine was not near as delectable."; else sRet="I dreamt last night about deboning a human woman and playing with her flesh."; break; } // Monster2 case 7: { // Pious if (nSpeaker==2) sRet="Aye, the wonderful voices of the choir just as the sun crested the horizon was a nice touch."; else sRet="The morning prayer today was quite nice."; break; } // Pious case 8: { // Nature if (nSpeaker==2) sRet="Lets hope it is not so."; else sRet="I had a dream that if more than a dream means dark times are coming."; break; } // Nature default: break; } // Language Switch break; } // Put Down/Dream/Light Chatter Line case 4: { // Recall Loved One/Place Line switch(nLang) { // Language Switch case 1: { // Ruffian if (nSpeaker==2) sRet="And I'm the Duke. If ya found a stone that size, why are ye still on guard duty for a copper a day?"; else sRet="...and in the chest was a gem big as my fist!"; break; } // Ruffian case 2: { // Noble if (nSpeaker==2) sRet="Don't remind me."; else sRet="My special one has beautiful eyes."; break; } // Noble case 3: { // Cant if (nSpeaker==2) sRet="Aye, if'n spoils ye has, Cuz ye seedy?"; else sRet="I've just milled some rum swag to bate."; break; } // Cant case 4: { // Mercenary if (nSpeaker==2) sRet="Aye, I had someone special when I was a young sprout your age."; else sRet="What about you?"; break; } // Mercenary case 5: { // Monster1 if (nSpeaker==2) sRet="Ach! It burns us! Evil light!"; else sRet="Me want dark cave."; break; } // Monster1 case 6: { // Monster2 if (nSpeaker==2) sRet="Yeah, me too. The portions of scalp that clung to those spikes always made me think of home."; else sRet="I miss the old pit with all its bloody spikes."; break; } // Monster2 case 7: { // Pious if (nSpeaker==2) sRet="Probably ascended to the higher planes, they were so kindly and good."; else sRet="What happened to them?"; break; } // Pious case 8: { // Nature if (nSpeaker==2) sRet="I agree that one's beauty is second to none. Except maybe someone I met long ago."; else sRet="…skin was pale and shined beneath the moonlight."; break; } // Nature default: break; } // Language Switch break; } // Recall Loved One/Place Line case 5: { // Bored Line switch(nLang) { // Language Switch case 1: { // Ruffian if (nSpeaker==2) sRet="I hear ye."; else sRet="I hope we have some excitement here soon."; break; } // Ruffian case 2: { // Noble if (nSpeaker==2) sRet="Surely, but we get paid to stand here."; else sRet="These days just seem to go on and on."; break; } // Noble case 3: { // Cant if (nSpeaker==2) sRet="Nay, I benar bother nix."; else sRet="Couch a hogshead in the strommel."; break; } // Cant case 4: { // Mercenary if (nSpeaker==2) sRet="So you'd rather have someone trying to stick a sword through your belly, then?"; else sRet="Even THIS much money isn't worth all this boredom."; break; } // Mercenary case 5: { // Monster1 if (nSpeaker==2) sRet="Rock chopper chucking!"; else sRet="Me want dwarf to throw at wall."; break; } // Monster1 case 6: { // Monster2 if (nSpeaker==2) sRet="Like squashing a baby or two? Harhar."; else sRet="Hell! I can think of much better things than standing here."; break; } // Monster2 case 7: { // Pious if (nSpeaker==2) sRet="Aye, not a single enemy seen for quite a time now."; else sRet="Peace at last."; break; } // Pious case 8: { // Nature if (nSpeaker==2) sRet="I agree. I am sure that tree over there was not there when we got here."; else sRet="Trees grow faster than time passes when standing this watch."; break; } // Nature default: break; } // Language Switch break; } // Bored Line default: break; } // phrase switch return sRet; } // fnBanter() int fnUnitCount(int nUC) { // count units int nRet=0; object oH=OBJECT_INVALID; int nC=0; while(nCnUC) nAllowed=nUC; nN=nRatio/nR2; if (nCountnAllowed) nRatio=1; //SendMessageToPC(GetFirstPC(),"SPAWN nRatio:"+IntToString(nRatio)+" nR2:"+IntToString(nR2)+" nR3:"+IntToString(nR3)); SetLocalInt(oMe,"nRatio",nRatio); SetLocalObject(oMe,"oGarrison"+IntToString(nCount),oSpawn); SetLocalInt(oSpawn,"bGarrison",TRUE); } // spawn is okay if (nSF==0) nSF=3; DelayCommand(IntToFloat(nSF)*60.0,fnSpawn(sR1,sR2,sR3,nR2,nR3,nUC,nSF)); } // fnSpawn() int fnIsBusy(object oNPC) { // is the object busy? int nRet=FALSE; object oAttacker=GetLastAttacker(); float fDist=-1.0; object oEnemy=GetNearestCreature(CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN,OBJECT_SELF,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,CREATURE_TYPE_IS_ALIVE,TRUE); if (oEnemy!=OBJECT_INVALID) return TRUE; if (IsInConversation(oNPC)==TRUE) return TRUE; if (!GetIsDead(oAttacker)) { // check on last attacker fDist=GetDistanceToObject(oAttacker); if (fDist!=-1.0&&fDist<20.0) return TRUE; } // check on last attacker return nRet; } // fnIsBusy() void fnReturnToGuardArea(object oNPC,object oArea) { // return to guard area if (fnIsBusy(oNPC)==FALSE) { // go ahead and return AssignCommand(oNPC,ClearAllActions()); AssignCommand(oNPC,ActionForceMoveToObject(oArea,FALSE,6.0,90.0)); } // go ahead and return else { // Busy SetLocalInt(oArea,"nAttacked",0); } // Busy } // fnReturnToGuardArea() void fnFindSpeechPartner(int nUnit,int nUC,int nLang,int nPhrase,object oSpawner,object oStarter) { int nUnitN=nUnit+1; object oPartner; if (nUnitN>nUC) nUnitN=1; oPartner=GetLocalObject(oSpawner,"oGarrison"+IntToString(nUnitN)); if ((oPartner!=OBJECT_INVALID&&GetIsDead(oPartner)!=TRUE)||oPartner==oStarter) { // speak DelayCommand(0.5,AssignCommand(oPartner,SpeakString(fnBanter(nLang,nPhrase,2)))); } // speak else { // keep searching via delay loop recursion DelayCommand(0.2,fnFindSpeechPartner(nUnitN,nUC,nLang,nPhrase,oSpawner,oStarter)); } // keep searching via delay loop recursion } // fnFindSpeechPartner() void fnSpeechAction(object oNPC,int nLang, int nUnit, object oSpawner) { // do speaking interplay object oPartner=OBJECT_INVALID; int nAt=GetLocalInt(oSpawner,"nAttacked"); int nR; int nUC=GetLocalInt(oSpawner,"nUnitCap"); nAt++; if (nAt>7) nAt=7; nR=Random(nAt)+1; if (nR>5) nR=5; SetLocalInt(oSpawner,"nAttacked",nAt); SetLocalInt(oSpawner,"nSpoken",TRUE); AssignCommand(oNPC,ClearAllActions()); AssignCommand(oNPC,SpeakString(fnBanter(nLang,nR,1))); fnFindSpeechPartner(nUnit,nUC,nLang,nR,oSpawner,oNPC); //SendMessageToPC(GetFirstPC(),"Speech: Partner["+IntToString(nC-1)+"] nLang:"+IntToString(nLang)+" Phrase:"+IntToString(nR)); } // fnSpeechAction() void fnDoSitAction(object oNPC) { // sit on chair if available else crosslegged object oChair=GetNearestObjectByTag("Chair",oNPC); float fDist=GetDistanceBetween(oNPC,oChair); if (fDist<10.0&&fDist!=0.0&&GetSittingCreature(oChair)==OBJECT_INVALID) { // do sit AssignCommand(oNPC,ClearAllActions()); AssignCommand(oNPC,ActionMoveToObject(oChair)); AssignCommand(oNPC,ActionSit(oChair)); } // do sit else { // crosslegged AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS,1.0,30.0)); } // crosslegged } // fnDoSitAction() void fnRandomCommand(object oNPC,int nLang, int nUnit, object oSpawner) { // Random Command int nR; // random object oH; // Object handle int nSpoken=GetLocalInt(oSpawner,"nSpoken"); int bBanterDisabled=GetLocalInt(GetModule(),"bBanterDisabled"); if (fnIsBusy(oNPC)==FALSE) { // go ahead and do random commands nR=Random(5)+1; //SendMessageToPC(GetFirstPC(),"fnRandomCommand("+GetTag(oNPC)+" #:"+IntToString(nR)+")"); switch(nR) { // random action switch case 1: {// do speech if(nSpoken==FALSE&&!bBanterDisabled)fnSpeechAction(oNPC,nLang,nUnit,oSpawner); break; } // do speech case 2: { // Sit in chair or Cross legged DelayCommand(5.0,fnDoSitAction(oNPC)); break; } // Sit in chair or Cross legged case 3: { // Random movement oH=GetNearestObject(OBJECT_TYPE_PLACEABLE,oSpawner,d20()); if (oH==OBJECT_INVALID) oH=GetNearestObject(OBJECT_TYPE_PLACEABLE,oSpawner,1); DelayCommand(5.1,AssignCommand(oNPC,ASActionMoveToObject(oH))); DelayCommand(13.1,AssignCommand(oNPC,ClearAllActions())); break; } // Random movement case 4: { // Look far animation DelayCommand(5.0,AssignCommand(oNPC,ClearAllActions())); DelayCommand(5.1,AssignCommand(oNPC,SetFacing(GetFacing(oSpawner)+180.0))); DelayCommand(5.2,AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_LOOPING_LOOK_FAR,1.0,10.0))); break; } // Look far animation case 5: { // bored animation DelayCommand(5.0,AssignCommand(oNPC,ClearAllActions())); DelayCommand(5.1,AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_BORED,1.0,10.0))); break; } // bored animation default: break; } // random action switch } // go ahead and do Random commands else { // Busy SetLocalInt(oSpawner,"nAttacked",0); } // Busy } // fnRandomCommand() void fnSubGarrison(object oUnit,int nUnit,int nLang,object oMe) { // actions for NPCS float fDist=GetDistanceBetween(oUnit,oMe); //SendMessageToPC(GetFirstPC(),"fnSubGarrison("+GetTag(oUnit)+")"); if (fDist>15.0||(fDist==0.0&&GetArea(oUnit)!=GetArea(oMe))) { // unit is too far away DelayCommand(3.0,fnReturnToGuardArea(oUnit,oMe)); } // unit is too far away else { // assign a random command DelayCommand(3.0,fnRandomCommand(oUnit,nLang,nUnit,oMe)); } // assign a random command } // fnSubGarrison() void fnGarrisonLoop(object oMe,int nUnit,int nUC, int nLang) { // delayed loop ANTI-TMI int nDelay=d4(); object oUnit=GetLocalObject(oMe,"oGarrison"+IntToString(nUnit)); //SendMessageToPC(GetFirstPC(),"fnGarrisonLoop("+GetTag(oMe)+",UNIT:"+IntToString(nUnit)+")"); if(oUnit!=OBJECT_INVALID&&GetIsDead(oUnit)!=TRUE) DelayCommand(IntToFloat(nDelay),fnSubGarrison(oUnit,nUnit,nLang,oMe)); if (nUnit39.9) { // okay to do things //SendMessageToPC(GetFirstPC(),"fnGarrison("+GetTag(oMe)+")"); SetLocalInt(oMe,"nSpoken",FALSE); if (GetLocalInt(oMe,"nSpawning")!=TRUE) { // initiate spawning fnSpawn(sRes1,sRes2,sRes3,nRatio2,nRatio3,nUnitCap,nSpawnFreq); SetLocalInt(oMe,"nSpawning",TRUE); } // initiate spawning if (GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oMe,1)!=OBJECT_INVALID) { // PC is near fnGarrisonLoop(oMe,1,nUnitCap,nLang); } // PC is near if (nActFreq<10) nActFreq=10; } // okay to do things DelayCommand(IntToFloat(nActFreq),fnGarrison()); } // fnGarrison() int fnLangChoose(string sIn) { // which language chosen int nRet=0; if (sIn=="RUFFIAN") nRet=1; else if (sIn=="NOBLE") nRet=2; else if (sIn=="CANT") nRet=3; else if (sIn=="MERCENARY") nRet=4; else if (sIn=="MONSTER1") nRet=5; else if (sIn=="MONSTER2") nRet=6; else if (sIn=="PIOUS") nRet=7; else if (sIn=="NATURE") nRet=8; return nRet; } // fnLangChoose() void fnInitializeGarrison() { // start the RTSA_GARRISON process object oMe=OBJECT_SELF; string sTag=GetTag(oMe); string sName=GetName(oMe); string sParse; int nN1; string sID=GetLocalString(oMe,"sTeamID"); object oMod=GetModule(); //SendMessageToPC(GetFirstPC(),"Initialize Garrison"); SetLocalString(oMe,"sTeamID",sID); nN1=GetLocalInt(oMod,"n"+sID+"Num"); SetLocalInt(oMe,"nTeamNum",nN1); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalString(oMe,"sRes1",sParse); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalString(oMe,"sRes2",sParse); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalString(oMe,"sRes3",sParse); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalInt(oMe,"nRatio2",StringToInt(sParse)); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalInt(oMe,"nRatio3",StringToInt(sParse)); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalInt(oMe,"nSpawnFreq",StringToInt(sParse)); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalInt(oMe,"nUnitCap",StringToInt(sParse)); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalInt(oMe,"nLang",fnLangChoose(sParse)); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalInt(oMe,"nActFreq",StringToInt(sParse)); DelayCommand(1.0,fnGarrison()); } // fnInitializeGarrison() void fnMoveThroughOuterPlanes(object oNPC) { // Try to escape the outer planes object oEscape=GetLocalObject(oNPC,"oEscapeDest"); float fD=GetLocalFloat(oNPC,"fEscapeDest"); if (oNPC!=OBJECT_INVALID) { // NPC exists if (GetArea(oEscape)!=GetArea(oNPC)||GetDistanceBetween(oNPC,oEscape)<1.5) { // not in same area or very close oEscape=GetNearestObjectByTag("DEAD_LEADER_WALK",oNPC,1); if (oEscape!=OBJECT_INVALID) { // move SetLocalObject(oNPC,"oEscapeDest",oEscape); SetLocalFloat(oNPC,"fEscapeDest",0.0); } // move else { // stuck SendMessageToPC(GetFirstPC(),"The leader '"+GetName(oNPC)+"' is stuck in area '"+GetName(GetArea(oNPC))+"!'"); } // stuck } // not in same area or very close else { // try to reach destination if (fD==0.0) { // first move phase AssignCommand(oNPC,ASActionMoveToObject(oEscape,TRUE,1.0)); fD=GetDistanceBetween(oNPC,oEscape); SetLocalFloat(oNPC,"fEscapeDest",fD); } // first move phase else if (fD!=GetDistanceBetween(oNPC,oEscape)) { // has moved fD=GetDistanceBetween(oNPC,oEscape); SetLocalFloat(oNPC,"fEscapeDest",fD); AssignCommand(oNPC,ASActionMoveToObject(oEscape,TRUE,1.0)); } // has moved else { // cannot reach destination try another oEscape=GetNearestObjectByTag("DEAD_LEADER_WALK",oNPC,1+d2()); if (oEscape==OBJECT_INVALID) oEscape=GetNearestObjectByTag("DEAD_LEADER_WALK",oNPC,1+d2()); if (oEscape==OBJECT_INVALID) oEscape=GetNearestObjectByTag("DEAD_LEADER_WALK",oNPC,1); if (oEscape==OBJECT_INVALID) SendMessageToPC(GetFirstPC(),"The leader '"+GetName(oNPC)+"' is stuck in area '"+GetName(GetArea(oNPC))+"!'"); else { // escape exists SetLocalObject(oNPC,"oEscapeDest",oEscape); SetLocalFloat(oNPC,"fEscapeDest",0.0); } // escape exists } // cannot reach destination try another } // try to reach destination } // NPC exists } // fnMoveThroughOuterPlanes() void fnLeaderAI(object oNPC,object oSpawner) { // do leader AI object oTarget; int nR; float fDist; string sID=GetLocalString(oNPC,"sTeamID"); oTarget=GetWaypointByTag(sID+"_START"); if (GetArea(oTarget)==GetArea(oNPC)) { // in lair DeleteLocalObject(oNPC,"oEscapeDest"); DeleteLocalFloat(oNPC,"fEscapeDest"); if(fnIsBusy(oNPC)==FALSE&&GetCurrentAction(oNPC)!=ACTION_MOVETOPOINT) { // okay to do stuff nR=d8(); switch(nR) { // action switch case 5: case 6: case 7: case 8: case 1: { // sit in throne AssignCommand(oNPC,ClearAllActions()); oTarget=GetNearestObjectByTag(sID,oNPC,1); if (oTarget==OBJECT_INVALID) oTarget=GetNearestObjectByTag("Throne_Evil",oNPC,1); if (oTarget==OBJECT_INVALID) oTarget=GetNearestObjectByTag("Throne_Good",oNPC,1); if (oTarget==OBJECT_INVALID) oTarget=GetNearestObjectByTag("Throne",oNPC,1); if (oTarget==OBJECT_INVALID) AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS,1.0,11.0)); else { // sit down in chair AssignCommand(oNPC,ActionMoveToObject(oTarget)); // AssignCommand(oNPC,ActionSit(oTarget)); } // sit down in chair break; } // sit in throne case 2: { // return to spawn area AssignCommand(oNPC,ClearAllActions()); AssignCommand(oNPC,ActionForceMoveToObject(oSpawner,TRUE,1.0,90.0)); break; } // return to spawn area case 3: { // random walk oTarget=GetNearestObject(OBJECT_TYPE_WAYPOINT,oNPC,d20()); if (oTarget==OBJECT_INVALID) oTarget=GetNearestObject(OBJECT_TYPE_WAYPOINT,oNPC,1); AssignCommand(oNPC,ASActionMoveToObject(oTarget)); break; } // random walk case 4: { // random animation nR=d6(); if (nR==1) AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD,1.0,4.0)); else if (nR==2) AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_BORED,1.0,3.0)); else if (nR==3) AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING,1.0,6.0)); else if (nR==4) AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_LOOPING_TALK_FORCEFUL,1.0,6.0)); else if (nR==5) AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_FIREFORGET_DRINK,1.0,3.0)); else if (nR==6) AssignCommand(oNPC,ActionPlayAnimation(ANIMATION_FIREFORGET_VICTORY1,1.0,3.0)); break; } // random animation default : break; } // action switch } // okay to do stuff } // in lair else if (fnIsBusy(oNPC)==FALSE&&oNPC!=OBJECT_INVALID) { // not in lair - get back fnMoveThroughOuterPlanes(oNPC); } // not in lair - get back if (oNPC!=OBJECT_INVALID) DelayCommand(2.0,AssignCommand(oNPC,ExecuteScript("ai_opponents",oNPC))); DelayCommand(12.0,fnLeaderAI(oNPC,oSpawner)); } // fnLeaderAI() void fnLevelUp(object oNPC,object oSpawner) { // level up the leader string sLUT=GetLocalString(oSpawner,"sLevelUpType"); object oMod=GetModule(); int nLT=GetLocalInt(oSpawner,"nLevelTime"); int nExp=GetLocalInt(oSpawner,"nLevelExp"); int nLvl; string sRes=GetResRef(oNPC); string sID=GetLocalString(oNPC,"sTeamID"); int nRV; object oSpawn; int nOpponentSpeed=GetLocalInt(oMod,"nOpponentSpeed"); // for future support of speeding or slowing the AI float fAIDelay=100.0; int bVerbose=GetLocalInt(oMod,"bVerboseAIMessaging"); // is verbose messaging on string sTeamName="Undead"; if (sID=="DWF") sTeamName="Dwarven"; else if (sID=="UNC") sTeamName="Unclean"; else if (sID=="SPID") sTeamName="Spider Cultists"; if (nOpponentSpeed<1) nOpponentSpeed=3; fAIDelay=fAIDelay*IntToFloat(nOpponentSpeed); nLT=GetLocalInt(GetModule(),"nAILevelSpeed"); if (nLT==0) nLT=GetLocalInt(oSpawner,"nLevelTime"); if (nExp==TRUE) { nLvl=GetLevelByPosition(1,oNPC); nLvl=nLvl+GetLevelByPosition(2,oNPC); nLvl=nLvl+GetLevelByPosition(3,oNPC); nLT=nLT+(2*(nLvl+1)); } if (bVerbose) { // verbose message fnMsgAllPlayers("The leader of "+sTeamName+" has just leveled to "+IntToString(nLvl+1)+". They will level again in "+IntToString(nLT)+" minutes."); } // verbose message if (sLUT=="A") { // level up using 1.30 or SoU DelayCommand(IntToFloat(nLT)*60.0,fnLevelUp(oNPC,oSpawner)); } // level up using 1.30 or SoU else { // resref increment method nRV=StringToInt(GetStringRight(sRes,2)); sRes=GetStringLeft(sRes,GetStringLength(sRes)-2); if (nRV!=0) { // levelup nRV++; if (nRV<10) sRes=sRes+"0"; sRes=sRes+IntToString(nRV); oSpawn=CreateObject(OBJECT_TYPE_CREATURE,sRes,GetLocation(oNPC),FALSE); SetLocalString(oSpawn,"sTeamID",sID); if (GetResRef(oSpawn)!=sRes) { // bad spawn stick with current leader DelayCommand(1.0,DestroyObject(oSpawn)); } // bad spawn stick with current leader else { // new leader SetLocalObject(oSpawner,"oLeader",oSpawn); //DelayCommand(fAIDelay,ExecuteScript("ai_opponents",oSpawn)); fnDespawnLeader(oNPC); if(nRV<20) DelayCommand(IntToFloat(nLT)*60.0,fnLevelUp(oSpawn,oSpawner)); DelayCommand(12.0,fnLeaderAI(oSpawn,oSpawner)); } // new leader } // levelup } // resref increment method } // fnLevelUp() void fnGarrisonL() { // Process Leader Garrison object oMod=GetModule(); object oMe=OBJECT_SELF; string sID=GetLocalString(oMe,"sTeamID"); object oPC=GetLocalObject(oMod,"oTeamLead"+sID); object oNPC=GetLocalObject(oMe,"oLeader"); string sRes=GetLocalString(oMe,"sRes"); int nLevel=GetLocalInt(oMe,"nLevelTime"); int nStartLevel=GetLocalInt(oMod,"nGSStartingLevel"); int nOpponentSpeed=GetLocalInt(oMod,"nOpponentSpeed"); // for future support of speeding or slowing the AI float fAIDelay=100.0; object oEnemy=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,oMe,1,CREATURE_TYPE_IS_ALIVE,TRUE); if(oEnemy==OBJECT_INVALID||GetDistanceBetween(oMe,oEnemy)>39.9) { // !ENEMY CLOSE if (nOpponentSpeed<1) nOpponentSpeed=3; fAIDelay=fAIDelay*IntToFloat(nOpponentSpeed); if (GetLocalInt(oMe,"nLevelExp")==TRUE) nLevel=nLevel+2; if (oPC==OBJECT_INVALID&&(oNPC==OBJECT_INVALID||GetIsDead(oNPC)==TRUE)) { // this team needs a leader if (nStartLevel>1) { // level other than 1 sRes=GetStringLeft(sRes,GetStringLength(sRes)-2); if (nStartLevel<10) sRes=sRes+"0"+IntToString(nStartLevel); else { sRes=sRes+IntToString(nStartLevel); } } // level other than 1 oNPC=CreateObject(OBJECT_TYPE_CREATURE,sRes,GetLocation(oMe),TRUE); SetLocalObject(oNPC,"oController",oMe); SetLocalObject(oMe,"oLeader",oNPC); SetLocalString(oNPC,"sTeamID",sID); if (oNPC==OBJECT_INVALID||GetResRef(oNPC)!=sRes) SendMessageToPC(GetFirstPC(),"GARRISON LEADER ERROR: Leader resref incorrect for ["+GetTag(oMe)+"] ResRef:'"+sRes+"'"); else { if (nStartLevel!=20) DelayCommand(IntToFloat(nLevel)*60.0,fnLevelUp(oNPC,oMe)); DelayCommand(12.0,fnLeaderAI(oNPC,oMe)); } } // this team needs a leader else if (oPC!=OBJECT_INVALID&&oNPC!=OBJECT_INVALID) { // destroy leader if (GetIsDead(oNPC)!=TRUE) { // valid AssignCommand(oNPC,ClearAllActions()); AssignCommand(oNPC,SpeakString("You may now control this team. Farewell.")); DelayCommand(4.0,fnDespawnLeader(oNPC)); } // valid DeleteLocalObject(oMe,"oLeader"); } // destroy leader } // !enemy close DelayCommand(120.0,fnGarrisonL()); // rerun every 2 minutes make sure leader } // fnGarrisonL() void fnInitializeLeader() { // start the RTSA_GARRISONL process object oMe=OBJECT_SELF; string sTag=GetTag(oMe); string sName=GetName(oMe); string sParse; int nN1; int nR; string sID=GetStringRight(sTag,GetStringLength(sTag)-7); object oMod=GetModule(); SetLocalString(oMe,"sTeamID",sID); nN1=GetLocalInt(oMod,"n"+sID+"Num"); SetLocalInt(oMe,"nTeamNum",nN1); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalString(oMe,"sRes",sParse); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); //SetLocalInt(oMe,"nLevelTime",StringToInt(sParse)); nR=GetLocalInt(GetModule(),"nAILevelSpeed"); if (nR==0) nR=15; SetLocalInt(oMe,"nLevelTime",nR); nN1=FALSE; sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); if (sParse=="T"||sParse=="TRUE"||sParse=="t") nN1=TRUE; SetLocalInt(oMe,"nLevelExp",nN1); sParse=fnParse(sName); sName=fnRemoveParsed(sName,sParse); SetLocalString(oMe,"sLevelUpType",sParse); DelayCommand(120.0,fnGarrisonL()); // give 2 minutes for team to be commanded } // fnInitializeLeader() /////////////////////////////////////////////// MAIN ///////////////////////////// void main() { if (GetFirstPC()!=OBJECT_INVALID&&GetLocalInt(GetModule(),"nInProgress")==TRUE) { // PCs are present if (GetLocalInt(OBJECT_SELF,"nGarrisoning")!=TRUE) { // initiate Garrison Process SetLocalInt(OBJECT_SELF,"nGarrisoning",TRUE); if(GetTag(OBJECT_SELF)=="RTSA_GARRISON") fnInitializeGarrison(); else if (GetLocalInt(GetModule(),"nAISetting")!=-1) fnInitializeLeader(); if (GetLocalInt(GetModule(),"nMonitorOn")!=TRUE) ExecuteScript("team_monitor",OBJECT_SELF); } // initiate Garrison Process } // PCs are present }