2025/07/20 Update
Added PEPS AI. Updated class & racialtypes 2DAs for the Lost Lands. Full compile.
This commit is contained in:
		
							
								
								
									
										172
									
								
								_module/nss/0c_assoc_actions.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								_module/nss/0c_assoc_actions.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,172 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_assoc_actions | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Conversation script that sets modes or allows oAssociate to do actions from a | ||||
|  conversation. | ||||
|  Param "sAction" | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| void main() | ||||
| { | ||||
|     object oPC = GetPCSpeaker(); | ||||
|     object oAssociate = OBJECT_SELF; | ||||
|     string sAssociateType = ai_GetAssociateType(oPC, oAssociate); | ||||
|     object oArea = GetArea(oAssociate); | ||||
|     string sAction = GetScriptParam("sAction"); | ||||
|     // Scout ahead is done int 0e_ch_1_hb (heartbeat script). | ||||
|     if(sAction == "Scout") | ||||
|     { | ||||
|         ai_ClearCreatureActions(); | ||||
|         ai_HaveCreatureSpeak(oAssociate, 4, ":29:35:46:"); | ||||
|         ai_SetAIMode(oAssociate, AI_MODE_SCOUT_AHEAD, TRUE); | ||||
|         ai_ScoutAhead(oAssociate); | ||||
|     } | ||||
|     else if(sAction == "BasicTactics") | ||||
|     { | ||||
|         SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, ""); | ||||
|         ai_SetAssociateAIScript(oAssociate, FALSE); | ||||
|     } | ||||
|     else if(sAction == "AmbushTactics") | ||||
|     { | ||||
|         SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_ambusher"); | ||||
|         SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_ambusher"); | ||||
|     } | ||||
|     else if(sAction == "DefensiveTactics") | ||||
|     { | ||||
|         SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_defensive"); | ||||
|         SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_defensive"); | ||||
|     } | ||||
|     else if(sAction == "RangedTactics") | ||||
|     { | ||||
|         SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_ranged"); | ||||
|         SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_ranged"); | ||||
|     } | ||||
|     else if(sAction == "Taunt") | ||||
|     { | ||||
|         SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_taunter"); | ||||
|         SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_taunter"); | ||||
|     } | ||||
|     else if(sAction == "CounterSpell") | ||||
|     { | ||||
|         SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_cntrspell"); | ||||
|         SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_cntrspell"); | ||||
|     } | ||||
|     else if(sAction == "PeaceTactics") | ||||
|     { | ||||
|         SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_peaceful"); | ||||
|     } | ||||
|     else if(sAction == "AttackTactics") | ||||
|     { | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_CHECK_ATTACK)) | ||||
|         { | ||||
|             ai_SetAIMode(oAssociate, AI_MODE_CHECK_ATTACK, FALSE); | ||||
|         } | ||||
|         else ai_SetAIMode(oAssociate, AI_MODE_CHECK_ATTACK, TRUE); | ||||
|     } | ||||
|     else if(sAction == "FollowCloser") ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType); | ||||
|     else if(sAction == "FollowFarther") ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType); | ||||
|     else if(sAction == "Pickup") ai_Loot(oPC, oAssociate, sAssociateType); | ||||
|     else if(sAction == "HealSelf") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 1); | ||||
|     else if(sAction == "HealAllies") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 2); | ||||
|     else if(sAction == "HealOutMinus") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType); | ||||
|     else if(sAction == "HealOutPlus") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType); | ||||
|     else if(sAction == "HealInMinus") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType); | ||||
|     else if(sAction == "HealInPlus") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType); | ||||
|     else if(sAction == "Traps") ai_Traps(oPC, oAssociate, sAssociateType); | ||||
|     else if(sAction == "Locks") ai_Locks(oPC, oAssociate, sAssociateType, 1); | ||||
|     else if(sAction == "Bash") ai_Locks(oPC, oAssociate, sAssociateType, 2); | ||||
|     else if(sAction == "Search") ai_Search(oPC, oAssociate, sAssociateType); | ||||
|     else if(sAction == "Stealth") ai_Stealth(oPC, oAssociate, sAssociateType); | ||||
|     else if(sAction == "NoMagic") ai_UseMagic(oPC, oAssociate, sAssociateType); | ||||
|     else if(sAction == "DefensiveCasting") ai_UseOffensiveMagic(oPC, oAssociate, TRUE, FALSE, sAssociateType); | ||||
|     else if(sAction == "OffensiveCasting") ai_UseOffensiveMagic(oPC, oAssociate, FALSE, TRUE, sAssociateType); | ||||
|     else if(sAction == "MagicMinus") ai_MagicIncrement(oPC, oAssociate, -1, sAssociateType); | ||||
|     else if(sAction == "MagicPlus") ai_MagicIncrement(oPC, oAssociate, 1, sAssociateType); | ||||
|     else if(sAction == "Speaking") | ||||
|     { | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK)) | ||||
|         { | ||||
|             ai_SetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK, FALSE); | ||||
|         } | ||||
|         else ai_SetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK, TRUE); | ||||
|     } | ||||
|     else if(sAction == "Ranged") | ||||
|     { | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_STOP_RANGED)) | ||||
|         { | ||||
|             ai_SetAIMode(oAssociate, AI_MODE_STOP_RANGED, FALSE); | ||||
|         } | ||||
|         else ai_SetAIMode(oAssociate, AI_MODE_STOP_RANGED, TRUE); | ||||
|     } | ||||
|     else if(sAction == "AtkAssociates") | ||||
|     { | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES)) | ||||
|         { | ||||
|             ai_SetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES, FALSE); | ||||
|         } | ||||
|         else ai_SetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES, TRUE); | ||||
|     } | ||||
|     else if(sAction == "BuffFirst") | ||||
|     { | ||||
|         if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER)) | ||||
|         { | ||||
|             ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER, FALSE); | ||||
|         } | ||||
|         else ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER, TRUE); | ||||
|     } | ||||
|     else if(sAction == "RestBuffing") | ||||
|     { | ||||
|         if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST)) | ||||
|         { | ||||
|             ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST, FALSE); | ||||
|         } | ||||
|         else ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST, TRUE); | ||||
|     } | ||||
|     else if(sAction == "Dispel") | ||||
|     { | ||||
|         if(ai_GetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL)) | ||||
|         { | ||||
|             ai_SetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL, FALSE); | ||||
|         } | ||||
|         else ai_SetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL, TRUE); | ||||
|     } | ||||
|     else if(sAction == "MagicItems") | ||||
|     { | ||||
|         if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS)) | ||||
|         { | ||||
|             ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS, FALSE); | ||||
|         } | ||||
|         else ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS, TRUE); | ||||
|     } | ||||
|     else if(sAction == "Identify") | ||||
|     { | ||||
|         ai_IdentifyAllVsKnowledge(oAssociate, oPC, oPC); | ||||
|         return; | ||||
|     } | ||||
|     else if(sAction == "GiveUnIdentifiedItems") | ||||
|     { | ||||
|         ai_ClearCreatureActions(); | ||||
|         object oItem = GetFirstItemInInventory(oAssociate); | ||||
|         while(oItem != OBJECT_INVALID) | ||||
|         { | ||||
|             if(!GetIdentified(oItem)) ActionGiveItem(oItem, oPC); | ||||
|             oItem = GetNextItemInInventory(oAssociate); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|     else if(sAction == "GiveMagicItems") | ||||
|     { | ||||
|         ai_ClearCreatureActions(); | ||||
|         itemproperty ipItemProp; | ||||
|         object oItem = GetFirstItemInInventory(oAssociate); | ||||
|         while(oItem != OBJECT_INVALID) | ||||
|         { | ||||
|             ipItemProp = GetFirstItemProperty(oItem); | ||||
|             if(GetIsItemPropertyValid(ipItemProp)) ActionGiveItem(oItem, oPC); | ||||
|             oItem = GetNextItemInInventory(oAssociate); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|     aiSaveAssociateModesToDb(oPC, oAssociate); | ||||
| } | ||||
							
								
								
									
										18
									
								
								_module/nss/0c_cast_polymorp.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								_module/nss/0c_cast_polymorp.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: 0c_cast_polymorp | ||||
|  Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Conversation script to have a henchman cast a polymorph spell. | ||||
|  int nSpell is the spell to cast. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_items" | ||||
| void main() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     int nSpell = StringToInt (GetScriptParam ("nSpell")); | ||||
|     // Save the original form so we can check when we turn back (Add 1 so we don't save a 0!). | ||||
|     SetLocalInt (oHenchman, AI_NORMAL_FORM, GetAppearanceType (oHenchman) + 1); | ||||
|     SetLocalString (oHenchman, AI_COMBAT_SCRIPT, "ai_a_polymorphed"); | ||||
|     ActionCastSpellAtObject (nSpell, oHenchman, 255, TRUE); | ||||
| } | ||||
|  | ||||
							
								
								
									
										15
									
								
								_module/nss/0c_fire_henchmen.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								_module/nss/0c_fire_henchmen.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_fire_henchmen | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Action taken script to fire/remove henchman for higher. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| void main() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     ai_ClearCreatureActions(); | ||||
|     ai_FireHenchman (GetPCSpeaker(), oHenchman); | ||||
|     PlayVoiceChat (VOICE_CHAT_GOODBYE, oHenchman); | ||||
| } | ||||
|  | ||||
							
								
								
									
										22
									
								
								_module/nss/0c_get_convo.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								_module/nss/0c_get_convo.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_get_convo | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Action taken script that leaves the current conversation and starts a new | ||||
|  conversation with oCreature using the linked conversation instead of the | ||||
|  ai_Henchman conversation. | ||||
|  | ||||
|  Allows use of ai_conversation for henchman in other modules. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void BeginOriginalHenchmanConversation(string sDialog, object oPC) | ||||
| { | ||||
|     BeginConversation(sDialog, oPC); | ||||
| } | ||||
| void main() | ||||
| { | ||||
|     ai_ClearCreatureActions(); | ||||
|     // Need to check special dialogs for HOTU henchman. | ||||
|     string sDialog = GetDialogFileToUse(GetLastSpeaker()); | ||||
|     DelayCommand(0.0, BeginOriginalHenchmanConversation(sDialog, GetPCSpeaker())); | ||||
| } | ||||
							
								
								
									
										25
									
								
								_module/nss/0c_get_henchman.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								_module/nss/0c_get_henchman.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_get_henchman | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Action taken script that adds oCreature to oPC's party as a henchman | ||||
|  while giving a random message. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     object oPC = GetPCSpeaker(); | ||||
|     AddHenchman(oPC, oCreature); | ||||
|     int nVoice; | ||||
|     switch(d4()) | ||||
|     { | ||||
|         case 1: nVoice = VOICE_CHAT_CANDO; break; | ||||
|         case 2: nVoice = VOICE_CHAT_CHEER; break; | ||||
|         case 3: nVoice = VOICE_CHAT_GOODIDEA; break; | ||||
|         case 4: nVoice = VOICE_CHAT_LAUGH; break; | ||||
|    } | ||||
|    PlayVoiceChat(nVoice, oCreature); | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										12
									
								
								_module/nss/0c_h_cast_spell.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								_module/nss/0c_h_cast_spell.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_cast_spell | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Action taken script that sets the specified spell to be cast. | ||||
|  Param | ||||
|  nSpell - the spell to cast. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| void main() | ||||
| { | ||||
|     SetLocalInt (OBJECT_SELF, "0_SPELL_TO_CAST", StringToInt (GetScriptParam ("nSpell"))); | ||||
| } | ||||
							
								
								
									
										81
									
								
								_module/nss/0c_henchmenspell.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								_module/nss/0c_henchmenspell.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| /*/////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_henchmenspell | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Action script to cast a specific spell for a henchman. | ||||
|  | ||||
|  Script Param | ||||
|  nTarget (INT) : 0 = ALL, 1 PC, 2 Caster, 3-6 = oPC's Henchman, 7 = PC's Familiar | ||||
|                  8 = PC's Animal Companion, 9 = PC's Summon. | ||||
|  nBuffType = 1 all 2 short 3 long, 4 healing, 5 lay on hands. | ||||
|  If nBuffType is 0 then it will cast a specific spell from | ||||
|  Variable "0_SPELL_TO_CAST". Use script: 0c_h_spell_cast spell to set the spell. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| float ai_UseLayOnHands(object oTarget, object oPC, float fDelay, object oCaster); | ||||
| void main() | ||||
| { | ||||
|     object oTarget, oPC = GetPCSpeaker(); | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     float fDelay; | ||||
|     int nTarget = StringToInt(GetScriptParam("nTarget")); | ||||
|     int nBuffType = StringToInt(GetScriptParam("nBuffType")); | ||||
|     // Cast a group of buff spells based on nBuffType and nTarget or a single spell. | ||||
|     if(nBuffType < 4) | ||||
|     { | ||||
|         // Cast a specific spell. | ||||
|         if(nBuffType == 0) | ||||
|         { | ||||
|             int nSpell = GetLocalInt(oCreature, "0_SPELL_TO_CAST"); | ||||
|             // These are buff spells so Acid fog (index 0) is not a valid spell. | ||||
|             if(nSpell > 0) | ||||
|             { | ||||
|                 ai_ClearCreatureActions(); | ||||
|                 object oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget)); | ||||
|                 if(oTarget != OBJECT_INVALID && ai_CheckAndCastSpell(oCreature, nSpell, 0, 0.0f, oTarget, oPC)) | ||||
|                 { | ||||
|                     DeleteLocalInt(oCreature, "0_SPELL_TO_CAST"); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_CANTDO, oCreature); | ||||
|                     string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))); | ||||
|                     ai_SendMessages("I cannot cast " + sSpellName + ".", AI_COLOR_RED, oPC); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // Cast a creatures buff spells on nTarget. | ||||
|         else ai_CastBuffs(oCreature, nBuffType, nTarget, oPC); | ||||
|     } | ||||
|     // Cast Healing spells. | ||||
|     else if(nBuffType == 4) | ||||
|     { | ||||
|         ai_SetupAllyTargets(oCreature, oPC); | ||||
|         oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget)); | ||||
|         ai_TryHealing(oCreature, oTarget); | ||||
|     } | ||||
|     // Use lay on hands. | ||||
|     else if(nBuffType == 5) | ||||
|     { | ||||
|         ai_SetupAllyTargets(oCreature, oPC); | ||||
|         oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget)); | ||||
|         ai_UseLayOnHands(oTarget, oPC, 0.0f, oCreature); | ||||
|     } | ||||
|     else if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_CUSS, oCreature); | ||||
| } | ||||
| float ai_UseLayOnHands(object oTarget, object oPC, float fDelay, object oCreature) | ||||
| { | ||||
|     int nHpLost = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget); | ||||
|     if(!nHpLost) | ||||
|     { | ||||
|         if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_CANTDO, oCreature); | ||||
|         ai_SendMessages(GetName(oTarget) + " does not need healed.", AI_COLOR_RED, oPC); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         ai_SendMessages(GetName(oCreature) + " is laying hands on " + GetName(oTarget), AI_COLOR_GREEN, oPC); | ||||
|         ActionUseFeat(FEAT_LAY_ON_HANDS, oTarget); | ||||
|         fDelay += 6.0f; | ||||
|     } | ||||
|     return fDelay; | ||||
| } | ||||
							
								
								
									
										16
									
								
								_module/nss/0c_if_a_magic_m.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								_module/nss/0c_if_a_magic_m.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_a_magic_m | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks to see if the henchmen has a specific | ||||
|  associate magic mode. | ||||
|  Param: | ||||
|  nMode - The mode to check. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     int nMode = StringToInt(GetScriptParam("nMode")); | ||||
|     return ai_GetMagicMode (oHenchman, nMode); | ||||
| } | ||||
							
								
								
									
										132
									
								
								_module/nss/0c_if_ass_convo.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								_module/nss/0c_if_ass_convo.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_ass_convo | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that has the henchman tell the player what options | ||||
|  have been selected. | ||||
|  | ||||
|  sOption will decide what the henchman says. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oPC = GetPCSpeaker(); | ||||
|     object oAssociate = OBJECT_SELF; | ||||
|     string sParam = GetScriptParam("sOption"); | ||||
|     if(sParam == "BaseMode") | ||||
|     { | ||||
|         string sBaseMode = "I'm ready to attack."; | ||||
|         string sVolume = " While shouting when I see things."; | ||||
|         // Lets get which base mode the henchman is in. | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_STAND_GROUND)) sBaseMode = "I'm holding here."; | ||||
|         else if(ai_GetAIMode(oAssociate, AI_MODE_DEFEND_MASTER)) sBaseMode = "I'm defending you."; | ||||
|         else if(ai_GetAIMode(oAssociate, AI_MODE_FOLLOW)) sBaseMode = "I'm following you."; | ||||
|         if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_peaceful") sBaseMode = "I will not fight the enemy!"; | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK)) sVolume = " While not speaking unless spoken to."; | ||||
|         SetCustomToken(AI_BASE_CUSTOM_TOKEN, sBaseMode + sVolume); | ||||
|     } | ||||
|     else if(sParam == "CombatTactics") | ||||
|     { | ||||
|         string sRangedUse = "", sCombatTactic = "I'm using my best judgement in combat "; | ||||
|         string sAtkAssociates = ""; | ||||
|         string sTargets = "against all enemies and "; | ||||
|         // Lets get which base mode the henchman is in. | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_CHECK_ATTACK)) sTargets = "against enemies I can handle and "; | ||||
|         if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_ambusher") sCombatTactic = "I'm using ambush tactics "; | ||||
|         else if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_defensive") sCombatTactic = "I'm using defensive tactics "; | ||||
|         else if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_taunter") sCombatTactic = "I'm ready to taunt "; | ||||
|         else if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_cntrspell") sCombatTactic = "I'm ready to counter spell "; | ||||
|         if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_peaceful") | ||||
|         { | ||||
|             sCombatTactic = "I will not fight the enemy!"; | ||||
|             sTargets = ""; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if(ai_GetAIMode(oAssociate, AI_MODE_STOP_RANGED)) sRangedUse = "will not use a ranged weapon."; | ||||
|             else sRangedUse = "will use a ranged weapon."; | ||||
|             if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES)) sAtkAssociates = " I will also ignore familiars, companions, and summons."; | ||||
|             else sAtkAssociates = " I will also attack familiars, companions, and summons."; | ||||
|         } | ||||
|         SetCustomToken(AI_BASE_CUSTOM_TOKEN + 1, sCombatTactic + sTargets + sRangedUse + sAtkAssociates); | ||||
|     } | ||||
|     else if(sParam == "Plans") | ||||
|     { | ||||
|         float fFollowRange = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE); | ||||
|         string sFollowRange = FloatToString(fFollowRange, 0, 0); | ||||
|         string sDistance = "I'm following from " + sFollowRange + " meters away while"; | ||||
|         string sStealth, sSearch, sPickup; | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_PICKUP_ITEMS)) sPickup = " picking up items"; | ||||
|         else sPickup = " not picking up any items"; | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_STEALTH)) sStealth = " in stealth"; | ||||
|         else sStealth = ""; | ||||
|         if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_SEARCH)) sSearch = " and searching"; | ||||
|         else sSearch = ""; | ||||
|         SetCustomToken(AI_BASE_CUSTOM_TOKEN + 2, sDistance + sPickup + sStealth + sSearch + "."); | ||||
|     } | ||||
|     else if(sParam == "Healing") | ||||
|     { | ||||
|         string sHealingIn = IntToString(GetLocalInt(oAssociate, AI_HEAL_IN_COMBAT_LIMIT)) + "%"; | ||||
|         string sHealingOut = IntToString(GetLocalInt(oAssociate, AI_HEAL_OUT_OF_COMBAT_LIMIT)) + "%"; | ||||
|         SetCustomToken(AI_BASE_CUSTOM_TOKEN + 5, "I'm healing our allies if they go below " + | ||||
|                  sHealingIn + " health in combat and " + sHealingOut + " out of combat."); | ||||
|     } | ||||
|     else if(sParam == "Spells") | ||||
|     { | ||||
|         string sCastingLevel = "[" + IntToString(GetLocalInt(oAssociate, AI_DIFFICULTY_ADJUSTMENT)) + "] "; | ||||
|         string sCasting = "I'm casting"; | ||||
|         string sType = " spells I choose."; | ||||
|         string sBuff = " I'll also targeting anyone that needs it "; | ||||
|         string sDispel = "while using Dispel spells."; | ||||
|         string sMagicItems = " Lastly I'll use any magic items I have."; | ||||
|         if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER)) sBuff = " Ofcourse I'll target you first "; | ||||
|         if(ai_GetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL)) sDispel = "while not using Dispel spells."; | ||||
|         if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_cntrspell") | ||||
|         { | ||||
|             sCasting = "I'm ready to counter spell our enemies."; | ||||
|             sType = ""; | ||||
|             sBuff = ""; | ||||
|             sDispel = ""; | ||||
|         } | ||||
|         if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC)) | ||||
|         { | ||||
|             sCasting = "I'm not use any magic."; | ||||
|             sType = ""; | ||||
|             sBuff = ""; | ||||
|             sDispel = ""; | ||||
|         } | ||||
|         else if(ai_GetMagicMode(oAssociate, AI_MAGIC_DEFENSIVE_CASTING)) sType = " defensive spells only."; | ||||
|         else if(ai_GetMagicMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING)) | ||||
|         { | ||||
|             sType = " offensive spells only."; | ||||
|             sBuff = ""; | ||||
|         } | ||||
|         else if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS)) sMagicItems = " Finally I'll not use magic items."; | ||||
|         SetCustomToken(AI_BASE_CUSTOM_TOKEN + 5, sCastingLevel + sCasting + sType + sBuff + sDispel+ sMagicItems); | ||||
|     } | ||||
|     else if(sParam == "Objects") | ||||
|     { | ||||
|         int bTraps = ai_GetAIMode(oAssociate, AI_MODE_DISARM_TRAPS); | ||||
|         int bLocks = ai_GetAIMode(oAssociate, AI_MODE_PICK_LOCKS); | ||||
|         int bBash = ai_GetAIMode(oAssociate, AI_MODE_BASH_LOCKS); | ||||
|         string sText = "I'm going to ignore all traps and locks."; | ||||
|         if(bTraps && bLocks && bBash) | ||||
|         { | ||||
|             sText = "I'm disarming all the traps and am either picking or bashing any of the locks we find."; | ||||
|         } | ||||
|         else if(bTraps && bLocks) sText = "I'm going to disarm all the traps and I'll pick all the locks we encounter."; | ||||
|         else if(bTraps && bBash) sText = "I shall disarm all the traps and will bash any locks we come across."; | ||||
|         else if(bTraps) sText = "I will disarm all the traps I can but will leave any locks for you to deal with."; | ||||
|         else if(bLocks && bBash) sText = "I will leave the traps for you but will either pick or bash any locks we see."; | ||||
|         else if(bLocks) sText = "I'll keep my distance from any traps we see, but will pick the locks found."; | ||||
|         else if(bBash) sText = "I'll let you mess with the traps, but I'll bash any locks that are out there."; | ||||
|         SetCustomToken(AI_BASE_CUSTOM_TOKEN + 3, sText); | ||||
|     } | ||||
|     else if(sParam == "RestBuffing") | ||||
|     { | ||||
|         string sRestBuffing = ""; | ||||
|         if(!ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST)) sRestBuffing = "not "; | ||||
|         SetCustomToken(AI_BASE_CUSTOM_TOKEN + 10, "After we rest I am " + sRestBuffing + "casting my long buff spells on us."); | ||||
|     } | ||||
|     return TRUE; | ||||
| } | ||||
							
								
								
									
										22
									
								
								_module/nss/0c_if_assoc_mode.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								_module/nss/0c_if_assoc_mode.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_assoc_mode | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks to see if the henchmen has a specific | ||||
|  associate mode. | ||||
|  Param: | ||||
|  nMode - The mode to check. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     int nMode = StringToInt(GetScriptParam("nMode")); | ||||
|     // This conversation line turns off picking up any items. | ||||
|     if (nMode == -1) | ||||
|     { | ||||
|         if(ai_SetAIMode (oHenchman, AI_MODE_PICKUP_ITEMS)) return TRUE; | ||||
|         return FALSE; | ||||
|     } | ||||
|     return ai_GetAIMode (oHenchman, nMode); | ||||
| } | ||||
							
								
								
									
										17
									
								
								_module/nss/0c_if_cntrspell.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								_module/nss/0c_if_cntrspell.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_cntrspell | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that returns TRUE the server allows a henchman to | ||||
|  use counterspell and if they don't have the counterspell ai script set. | ||||
|  Param: | ||||
|  sAIScript - The special combat script to check. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     return (AI_COUNTERSPELLING_ON && | ||||
|             ai_CheckClassType(oHenchman, AI_CLASS_TYPE_CASTER) && | ||||
|             GetLocalString(oHenchman, AI_COMBAT_SCRIPT) != "ai_a_cntrspell"); | ||||
| } | ||||
							
								
								
									
										16
									
								
								_module/nss/0c_if_com_script.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								_module/nss/0c_if_com_script.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_com_script | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that returns TRUE the caller does have an ai combat | ||||
|  script set to sAIScript. | ||||
|  Param: | ||||
|  sAIScript - The special combat script to check. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     string sAIScript = GetScriptParam("sAIScript"); | ||||
|     string sAICombatScript = GetLocalString (OBJECT_SELF, AI_COMBAT_SCRIPT); | ||||
|     return (sAIScript == sAICombatScript); | ||||
| } | ||||
							
								
								
									
										21
									
								
								_module/nss/0c_if_convo.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								_module/nss/0c_if_convo.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_if_convo | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that check if oCreature has a linked conversation. | ||||
|  Only checks for Henchman. | ||||
|  Allows use of ai_conversation for henchman in other modules. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "nw_inc_gff" | ||||
| #include "0i_messages" | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     if(GetAssociateType(oHenchman) == ASSOCIATE_TYPE_HENCHMAN) | ||||
|     { | ||||
|         json jHenchman = ObjectToJson(oHenchman); | ||||
|         string sConversation = JsonGetString(GffGetResRef(jHenchman, "Conversation")); | ||||
|         if(sConversation != "") return TRUE; | ||||
|     } | ||||
|     return FALSE; | ||||
| } | ||||
							
								
								
									
										18
									
								
								_module/nss/0c_if_has_assoc.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								_module/nss/0c_if_has_assoc.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_has_assoc | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks to see if caller has the specified feat | ||||
|  to summon either a companion or a familiar and they are not summoned. | ||||
|  Param | ||||
|  sAssociate - "Familiar" or "Companion" | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     string sAssociate = GetScriptParam("sAssociate"); | ||||
|     if(sAssociate == "Familiar" && GetHasFeat(FEAT_SUMMON_FAMILIAR, oHenchman) && | ||||
|         GetAssociate(ASSOCIATE_TYPE_FAMILIAR) == OBJECT_INVALID) return TRUE; | ||||
|     return (sAssociate == "Companion" && GetHasFeat(FEAT_ANIMAL_COMPANION, oHenchman) && | ||||
|              GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION) == OBJECT_INVALID); | ||||
| } | ||||
							
								
								
									
										28
									
								
								_module/nss/0c_if_has_class.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								_module/nss/0c_if_has_class.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_has_class | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks to see if conversation owner has a | ||||
|  specified class. Multiple classes maybe selected. | ||||
|  Param | ||||
|  nClass# - the class to look for use nClass1, nClass2, nClass3 for each one to check. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     int nCntr = 1; | ||||
|     int nClass; | ||||
|     string sClass; | ||||
|     while(nCntr < 10) | ||||
|     { | ||||
|         sClass = GetScriptParam("nClass" + IntToString(nCntr)); | ||||
|         if(sClass != "") | ||||
|         { | ||||
|             nClass = StringToInt(sClass); | ||||
|             if(GetLevelByClass(nClass, oHenchman)) return TRUE; | ||||
|             nCntr++; | ||||
|         } | ||||
|         else break; | ||||
|     } | ||||
|     return FALSE; | ||||
| } | ||||
							
								
								
									
										22
									
								
								_module/nss/0c_if_has_feat.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								_module/nss/0c_if_has_feat.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_has_feat | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks to see if they have a specific feat. | ||||
|  Param: | ||||
|  sTarget - either "OBJECT_SELF", or "PCSpeaker", blanks defaults to "PCSpeaker" | ||||
|  nFeat - the feat number from Feats.2da | ||||
|  bNot - if 1 TRUE then this returns true for the target not having the feat. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_main" | ||||
| int StartingConditional() | ||||
| { | ||||
|     string sTarget = GetScriptParam("sTarget"); | ||||
|     int nFeat = StringToInt(GetScriptParam("nFeat")); | ||||
|     int bNot = StringToInt(GetScriptParam("bNot")); | ||||
|     object oCreature; | ||||
|     if(sTarget == "OBJECT_SELF") oCreature = OBJECT_SELF; | ||||
|     else if(sTarget == "" || sTarget == "PCSpeaker") oCreature = GetPCSpeaker(); | ||||
|     if(bNot) return !GetHasFeat(nFeat, oCreature); | ||||
|     return (GetHasFeat(nFeat ,oCreature) || ai_GetIsDungeonMaster(oCreature)); | ||||
| } | ||||
							
								
								
									
										26
									
								
								_module/nss/0c_if_has_spell.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								_module/nss/0c_if_has_spell.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_has_spell | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks to see if caster can cast the specified spell. | ||||
|  Param | ||||
|  nSpell# - the spell to look for nSpell1, sSpell2, nSpell3 for each spell to check. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_spells" | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oCaster = OBJECT_SELF; | ||||
|     int nCnt = 1; | ||||
|     int nSpell; | ||||
|     string sSpell; | ||||
|     while(nCnt < 20) | ||||
|     { | ||||
|         sSpell = GetScriptParam("nSpell" + IntToString(nCnt)); | ||||
|         if(sSpell == "") return FALSE; | ||||
|         nSpell = StringToInt(sSpell); | ||||
|         if(GetHasSpell(nSpell, oCaster)) return TRUE; | ||||
|         //else if(ai_GetKnownSpell(oCaster, nSpell)) return TRUE; | ||||
|         nCnt++; | ||||
|     } | ||||
|     return FALSE; | ||||
| } | ||||
							
								
								
									
										12
									
								
								_module/nss/0c_if_hen_leave.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								_module/nss/0c_if_hen_leave.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_hen_leave | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that check if allowing the player to remove a henchman | ||||
|  is activated on this server. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     return AI_REMOVE_HENCHMAN_ON; | ||||
| } | ||||
							
								
								
									
										17
									
								
								_module/nss/0c_if_identify.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								_module/nss/0c_if_identify.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_identify | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks to see if the henchmen has a better lore | ||||
|  skill than the speaker. | ||||
|  Also checks AI_IDENTIFY_ON to see if the server wants them to help. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     if (!AI_IDENTIFY_ON && !ai_CanISpeak (oHenchman)) return FALSE; | ||||
|     int nHenchmanLore = GetSkillRank(SKILL_LORE, oHenchman); | ||||
|     int nMasterLore = GetSkillRank(SKILL_LORE, GetMaster(oHenchman)); | ||||
|     return (nHenchmanLore > nMasterLore); | ||||
| } | ||||
							
								
								
									
										11
									
								
								_module/nss/0c_if_not_master.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								_module/nss/0c_if_not_master.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_not_master | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks if the speaker is the master of this | ||||
|  henchman. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| int StartingConditional() | ||||
| { | ||||
|     return !GetIsObjectValid(GetMaster()); | ||||
| } | ||||
							
								
								
									
										13
									
								
								_module/nss/0c_if_open_inven.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								_module/nss/0c_if_open_inven.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_open_equip | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks if opening a henchmans inventory | ||||
|  is activated on this server. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     if(GetAssociateType(OBJECT_SELF) != ASSOCIATE_TYPE_HENCHMAN) return FALSE; | ||||
|     return AI_OPEN_INVENTORY; | ||||
| } | ||||
							
								
								
									
										12
									
								
								_module/nss/0c_if_pickuploot.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								_module/nss/0c_if_pickuploot.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_pickuploot | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that check if having associates picking up loot is | ||||
|  activated on this server. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     return AI_PICKUP_LOOT; | ||||
| } | ||||
							
								
								
									
										11
									
								
								_module/nss/0c_if_polymorph.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								_module/nss/0c_if_polymorph.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_polymorph | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks to see if the caller is polymorphed. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     if (GetLocalInt(OBJECT_SELF, AI_NORMAL_FORM) != 0) return TRUE; | ||||
|     return FALSE; | ||||
| } | ||||
							
								
								
									
										11
									
								
								_module/nss/0c_if_scout.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								_module/nss/0c_if_scout.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_scout | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that check if scouting is activated on this server. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     return AI_SCOUT_AHEAD_ON; | ||||
| } | ||||
							
								
								
									
										18
									
								
								_module/nss/0c_if_skillrank.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								_module/nss/0c_if_skillrank.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_SkillRank | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that checks to see if the caller's skill ranks | ||||
|  are above or equal to the param value. | ||||
|  Param: | ||||
|  nSkill - the skill number for the skill. See skills.2da. | ||||
|  nRank - the rank required. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_main" | ||||
| int StartingConditional() | ||||
| { | ||||
|     string sSkill = GetScriptParam("nSkill"); | ||||
|     if(sSkill == "") return FALSE; | ||||
|     int nRank = StringToInt(GetScriptParam("nRank")); | ||||
|     return (GetSkillRank(StringToInt(sSkill)) >= nRank); | ||||
| } | ||||
							
								
								
									
										15
									
								
								_module/nss/0c_if_taunt.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								_module/nss/0c_if_taunt.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_if_taunt | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that returns TRUE the server allows a henchman to | ||||
|  taunt and if they have the don't have the taunt ai script set. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     object oHenchman = OBJECT_SELF; | ||||
|     return (AI_TAUNTING_ON && | ||||
|             GetSkillRank(SKILL_TAUNT, oHenchman) > ai_GetCharacterLevels(oHenchman) && | ||||
|             GetLocalString(oHenchman, AI_COMBAT_SCRIPT) != "ai_a_taunter"); | ||||
| } | ||||
							
								
								
									
										19
									
								
								_module/nss/0c_listhenchman.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								_module/nss/0c_listhenchman.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: 0c_cast_polymorp | ||||
|  Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Conversation script to setup the tokens for the henchman in the speakers party | ||||
|  except for who they are talking to. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| void main() | ||||
| { | ||||
|     object oSpeaker = OBJECT_SELF; | ||||
|     object oPC = GetPCSpeaker(); | ||||
|     int nCntr = 1; | ||||
|     object oHenchman = GetHenchman(oPC, nCntr); | ||||
|     while(oHenchman != OBJECT_INVALID) | ||||
|     { | ||||
|         if(oHenchman != oSpeaker) SetCustomToken(77100 + nCntr, GetName(oHenchman)); | ||||
|         oHenchman = GetHenchman(oPC, ++nCntr); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										27
									
								
								_module/nss/0c_no_com_script.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								_module/nss/0c_no_com_script.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0c_no_com_script | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Text Appears When script that returns TRUE the caller does not have an ai combat | ||||
|  script set to sAIScript. | ||||
|  if sAIScript is blank then if its equal to all of them. | ||||
|  Param: sAIScripts:"ai_a_ambusher", "ai_a_defensive", "ai_a_taunter", "ai_coward". | ||||
|  sAIScript - The special combat script to check. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| int StartingConditional() | ||||
| { | ||||
|     string sAIScript = GetScriptParam("sAIScript"); | ||||
|     string sAICombatScript = GetLocalString (OBJECT_SELF, AI_COMBAT_SCRIPT); | ||||
|     // This is the value for do your own thing in combat! | ||||
|     if (sAIScript == "") | ||||
|     { | ||||
|         return (sAICombatScript == "ai_a_ambusher" || | ||||
|                 sAICombatScript == "ai_a_defensive" || | ||||
|                 sAICombatScript == "ai_a_ranged" || | ||||
|                 sAICombatScript == "ai_a_taunter" || | ||||
|                 sAICombatScript == "ai_a_cntrspell" || | ||||
|                  sAICombatScript == "ai_a_peaceful"); | ||||
|     } | ||||
|     return (sAIScript != sAICombatScript); | ||||
| } | ||||
							
								
								
									
										14
									
								
								_module/nss/0c_remove_effect.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								_module/nss/0c_remove_effect.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script:0c_remove_effect | ||||
|  Programmer:Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Actions Taken script that removes an effect from OBJECT_SELF. | ||||
|  Param: nEffect - the EFFECT_TYPE_* number to remove. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_spells" | ||||
| void main () | ||||
| { | ||||
|     int nEffect = StringToInt (GetScriptParam ("nEffectType")); | ||||
|     ai_RemoveASpecificEffect (OBJECT_SELF, nEffect); | ||||
| } | ||||
|  | ||||
							
								
								
									
										17
									
								
								_module/nss/0c_summon_assoc.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								_module/nss/0c_summon_assoc.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: 0c_summon_assoc | ||||
|  Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Conversation script to have the caller summon either an animal companion or | ||||
|  familiar associate. | ||||
|  | ||||
|  Param | ||||
|  sAssociate - which associate to summon. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| void main() | ||||
| { | ||||
|     string sAssociate = GetScriptParam ("sAssociate"); | ||||
|     if (sAssociate == "Familiar") SummonFamiliar (); | ||||
|     else if (sAssociate == "Companion") SummonAnimalCompanion (); | ||||
| } | ||||
							
								
								
									
										15
									
								
								_module/nss/0c_use_feat.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								_module/nss/0c_use_feat.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: 0c_summon_assoc | ||||
|  Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Conversation script to have the caller use nFeat from the feat.2da. | ||||
|  | ||||
|  Param | ||||
|  nFeat - Feat number from the feat.2da. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| void main() | ||||
| { | ||||
|     int nFeat = StringToInt (GetScriptParam ("nFeat")); | ||||
|     ActionUseFeat(nFeat, OBJECT_SELF); | ||||
| } | ||||
							
								
								
									
										16
									
								
								_module/nss/0e_c2_1_hb.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								_module/nss/0e_c2_1_hb.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_c2_1_hb | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|   Monster OnHeartbeat script; | ||||
|   This will usually fire every 6 seconds (1 game round). | ||||
|  | ||||
|   I am reverting the AI script back to the games default scripts for efficiency. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_module" | ||||
| void main() | ||||
| { | ||||
|     SetLocalInt(OBJECT_SELF, AI_ONSPAWN_EVENT, TRUE); | ||||
|     ai_ChangeEventScriptsForMonster(OBJECT_SELF); | ||||
|     ExecuteScript("nw_c2_default1"); | ||||
| } | ||||
							
								
								
									
										34
									
								
								_module/nss/0e_c2_7_ondeath.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								_module/nss/0e_c2_7_ondeath.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_c2_7_ondeath | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|   Monster OnDeath script; | ||||
|   This fires when the creature dies. | ||||
| *//////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_module" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Added code to allow for permanent associates in the battle! | ||||
|     object oModule = GetModule(); | ||||
|     if(AI_DEBUG) ai_Debug("0e_c2_7_ondeath", "14", "AI_RULE_PERM_ASSOC: " + IntToString(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))); | ||||
|     if(GetLocalInt(oModule, AI_RULE_PERM_ASSOC)) | ||||
|     { | ||||
|         object oAssociate; | ||||
|         int nIndex; | ||||
|         for(nIndex = 2; nIndex < 6; nIndex++) | ||||
|         { | ||||
|             oAssociate = GetAssociate(nIndex, oCreature); | ||||
|             if(oAssociate != OBJECT_INVALID) | ||||
|             { | ||||
|                 SetIsDestroyable(FALSE, FALSE, FALSE, oAssociate); | ||||
|                 DelayCommand(0.1, ChangeToStandardFaction(oAssociate, STANDARD_FACTION_HOSTILE)); | ||||
|                 DelayCommand(3.0, SetIsDestroyable(TRUE, FALSE, FALSE, oAssociate)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     if(GetLocalInt(oModule, AI_RULE_CORPSES_STAY)) SetIsDestroyable(FALSE, FALSE, TRUE); | ||||
|     ai_ClearCombatState(oCreature); | ||||
|     ExecuteScript(GetLocalString(oCreature, "AI_ON_DEATH")); | ||||
| } | ||||
|  | ||||
							
								
								
									
										14
									
								
								_module/nss/0e_ch_1_hb.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								_module/nss/0e_ch_1_hb.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_ch_1_hb | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|   Associate(Summons, Familiar, Companion) OnHeart beat script when out of combat; | ||||
|   This will usually fire every 6 seconds (1 game round). | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_module" | ||||
| void main() | ||||
| { | ||||
|     SetLocalInt(OBJECT_SELF, AI_ONSPAWN_EVENT, TRUE); | ||||
|     ai_ChangeEventScriptsForAssociate(OBJECT_SELF); | ||||
|     ExecuteScript("nw_ch_ac1"); | ||||
| } | ||||
							
								
								
									
										42
									
								
								_module/nss/0e_ch_7_ondeath.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								_module/nss/0e_ch_7_ondeath.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_ch_7_ondeath | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|   Associate OnSpawn script; | ||||
|   This fires when an associate dies. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_module" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Added code to allow for permanent associates in the battle! | ||||
|     if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "13", GetName(oCreature) + " has died!" + | ||||
|                  " AI_RULE_PERM_ASSOC: " + IntToString(GetLocalInt(GetModule(), AI_RULE_PERM_ASSOC))); | ||||
|     object oModule = GetModule(); | ||||
|     if(GetLocalInt(oModule, AI_RULE_PERM_ASSOC)) | ||||
|     { | ||||
|         object oAssociate; | ||||
|         int nIndex; | ||||
|         for(nIndex = 2; nIndex < 6; nIndex++) | ||||
|         { | ||||
|             oAssociate = GetAssociate(nIndex, oCreature); | ||||
|             if(oAssociate != OBJECT_INVALID) | ||||
|             { | ||||
|                 SetIsDestroyable(FALSE, FALSE, FALSE, oAssociate); | ||||
|                 DelayCommand(0.1, ChangeToStandardFaction(oAssociate, STANDARD_FACTION_HOSTILE)); | ||||
|                 DelayCommand(3.0, SetIsDestroyable(TRUE, FALSE, FALSE, oAssociate)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     // Remove the widget! | ||||
|     object oPC = GetMaster(oCreature); | ||||
|     if(oPC != OBJECT_INVALID) | ||||
|     { | ||||
|         NuiDestroy(oPC, NuiFindWindow(oPC, ai_GetAssociateType(oPC, oCreature) + AI_WIDGET_NUI)); | ||||
|         DelayCommand(0.5, ai_CheckXPPartyScale(oCreature)); | ||||
|         DelayCommand(2.0, ai_ClearCreatureActions(TRUE)); | ||||
|     } | ||||
|     DelayCommand(2.0, ai_ClearCombatState(oCreature)); | ||||
|     ExecuteScript(GetLocalString(oCreature, "AI_ON_DEATH")); | ||||
| } | ||||
|  | ||||
							
								
								
									
										22
									
								
								_module/nss/0e_do_combat_rnd.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								_module/nss/0e_do_combat_rnd.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_do_combat_rnd | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|     Used to execute a combat round just after the current action is over. | ||||
|     Note: Do not use with an attack action since it will continue until | ||||
|     the attacked enemy is dead. We end attack actions with a ClearAllActions | ||||
|     command and would also end this one so it will not work with attack actions. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     if(AI_DEBUG) ai_Debug("0e_do_combat_rnd", "14", GetName(oCreature) + " is calculating a new round." + | ||||
|                  "nAction: " + IntToString(GetCurrentAction(oCreature))); | ||||
|     if(ai_GetIsInCombat(oCreature)) | ||||
|     { | ||||
|         if(GetAssociateType(oCreature) == ASSOCIATE_TYPE_NONE && | ||||
|            !ai_GetIsCharacter(oCreature)) ai_DoMonsterCombatRound(oCreature); | ||||
|         else if(ai_CanIAttack(oCreature)) ai_DoAssociateCombatRound(oCreature); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										60
									
								
								_module/nss/0e_gui_events.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								_module/nss/0e_gui_events.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: 0e_gui_events | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  OnPlayerGUIEvent event script | ||||
|     Used to allow PEPS to gain control of specific GUI events. | ||||
|  | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_gui_events" | ||||
| #include "0i_menus" | ||||
| void main() | ||||
| { | ||||
|     object oPC = GetLastGuiEventPlayer(); | ||||
|     int nEventType = GetLastGuiEventType(); | ||||
|     int nEventInt = GetLastGuiEventInteger(); | ||||
|     //object oEventObject = GetLastGuiEventObject(); | ||||
|     switch(nEventType) | ||||
|     { | ||||
|         case GUIEVENT_EFFECTICON_CLICK: | ||||
|         { | ||||
|             if(ai_GetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT)) | ||||
|             { | ||||
|                 ai_CreateEffectChatReport(oPC, nEventInt); | ||||
|                 return; | ||||
|             } | ||||
|             int nToken = NuiFindWindow(oPC, AI_EFFECT_ICON_NUI); | ||||
|             json jData; | ||||
|             if(nToken) | ||||
|             { | ||||
|                 jData = NuiGetUserData(oPC, nToken); | ||||
|                 int nOldEffectIcon = JsonGetInt(JsonArrayGet(jData, 1)); | ||||
|                 DelayCommand(0.0, NuiDestroy(oPC, nToken)); | ||||
|                 if(nOldEffectIcon == nEventInt) return; | ||||
|             } | ||||
|             ai_CreateEffectIconMenu(oPC, nEventInt); | ||||
|         } | ||||
|         case GUIEVENT_PARTYBAR_PORTRAIT_CLICK: | ||||
|         { | ||||
|             object oAssociate = GetLastGuiEventObject(); | ||||
|             if(GetMaster(oAssociate) == oPC) | ||||
|             { | ||||
|                 // If all the Command buttons are blocked then don't load the menu. | ||||
|                 if(GetLocalInt(GetModule(), sDMWidgetAccessVarname) != 7340028) | ||||
|                 { | ||||
|                     string sAssociateType = ai_GetAssociateType(oPC, oAssociate); | ||||
|                     if(IsWindowClosed(oPC, sAssociateType + AI_COMMAND_NUI)) | ||||
|                     { | ||||
|                         ai_CreateAssociateCommandNUI(oPC, oAssociate); | ||||
|                     } | ||||
|                     IsWindowClosed(oPC, sAssociateType + AI_NUI); | ||||
|                     IsWindowClosed(oPC, sAssociateType + AI_LOOTFILTER_NUI); | ||||
|                     IsWindowClosed(oPC, sAssociateType + AI_COPY_NUI); | ||||
|                     IsWindowClosed(oPC, sAssociateType + AI_QUICK_WIDGET_NUI); | ||||
|                     IsWindowClosed(oPC, sAssociateType + AI_SPELL_MEMORIZE_NUI); | ||||
|                     IsWindowClosed(oPC, sAssociateType + AI_SPELL_KNOWN_NUI); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										277
									
								
								_module/nss/0e_id_events.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								_module/nss/0e_id_events.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,277 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0e_id_events | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|     Infinite Dungeons monster event handler. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| #include "x0_i0_assoc" | ||||
| // Followers special heartbeat script. | ||||
| void ai_hen_id1_heart(object oCreature); | ||||
| // Followers special conversation script. | ||||
| void ai_hen_id1_convo(object oCreature, int nMatch); | ||||
| // Followers special perception script. | ||||
| void ai_hen_id1_percept(object oCreature); | ||||
| // Followers special end of round script. | ||||
| void ai_hen_id1_endcombat(object oCreature, int bFollower); | ||||
| // Followers special castat script. | ||||
| void ai_hen_id1_castat(object oCreature); | ||||
|  | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     int nEvent = GetCurrentlyRunningEvent(); | ||||
|     int bFollower = GetLocalInt(oCreature, "bFollower"); | ||||
|     //WriteTimestampedLogEntry("0e_id_events [24] " + GetName(oCreature) + " nEvent: " + IntToString(nEvent) + | ||||
|     //                         " bFollower: " + IntToString(bFollower)); | ||||
|     switch (nEvent) | ||||
|     { | ||||
|         case EVENT_SCRIPT_CREATURE_ON_HEARTBEAT: | ||||
|         { | ||||
|             if(bFollower) ai_hen_id1_heart(oCreature); | ||||
|             else ExecuteScript("nw_c2_default1", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_NOTICE: | ||||
|         { | ||||
|             if(bFollower) ai_hen_id1_percept(oCreature); | ||||
|             else ExecuteScript("nw_c2_default2", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_DIALOGUE: | ||||
|         { | ||||
|             int nMatch = GetListenPatternNumber(); | ||||
|             if(nMatch == -1) | ||||
|             { | ||||
|                 if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature) || | ||||
|                    GetLocalInt(oCreature, AI_AM_I_SEARCHING)) return; | ||||
|                 ai_ClearCreatureActions(); | ||||
|                 string sConversation = GetLocalString(oCreature, "sConversation"); | ||||
|                 if(sConversation != "") BeginConversation(sConversation); | ||||
|                 else BeginConversation(); | ||||
|             } | ||||
|             if(bFollower) ai_hen_id1_convo(oCreature, nMatch); | ||||
|             else ExecuteScript("nw_c2_default4", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED: | ||||
|         { | ||||
|             if(bFollower) ExecuteScript("nw_ch_ac5", oCreature); | ||||
|             else ExecuteScript("nw_c2_default5", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_DAMAGED: | ||||
|         { | ||||
|             if(bFollower) ExecuteScript("nw_ch_ac6", oCreature); | ||||
|             else ExecuteScript("nw_c2_default6", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT: | ||||
|         { | ||||
|             if(bFollower) ai_hen_id1_castat(oCreature); | ||||
|             else ExecuteScript("nw_c2_defaultb", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND: | ||||
|         { | ||||
|             ai_hen_id1_endcombat(oCreature, bFollower); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR: | ||||
|         { | ||||
|             if(bFollower) ExecuteScript("nw_ch_ace", oCreature); | ||||
|             else ExecuteScript("nw_c2_defaulte", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_RESTED: | ||||
|         { | ||||
|             if(bFollower) ExecuteScript("nw_ch_aca", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_DISTURBED: | ||||
|         { | ||||
|             if(bFollower) ExecuteScript("nw_ch_ac8", oCreature); | ||||
|             else ExecuteScript("nw_c2_default8", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_DEATH: | ||||
|         { | ||||
|             if(bFollower) ExecuteScript("nw_ch_ac7", oCreature); | ||||
|             else | ||||
|             { | ||||
|                 ExecuteScript("nw_c2_default7", oCreature); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ai_hen_id1_heart(object oCreature) | ||||
| { | ||||
|     // Sometimes they slip out of this mode! | ||||
|     if(GetAssociateState(NW_ASC_MODE_DYING, oCreature) && | ||||
|        GetCommandable()) | ||||
|     { | ||||
|         ActionPlayAnimation(ANIMATION_LOOPING_DEAD_FRONT, 1.0, 65.0); | ||||
|         SetCommandable(FALSE); | ||||
|     } | ||||
|     ExecuteScript("nw_ch_ac1", oCreature); | ||||
| } | ||||
| void ai_hen_id1_convo(object oCreature, int nMatch) | ||||
| { | ||||
|     if(nMatch == ASSOCIATE_COMMAND_INVENTORY) | ||||
|     { | ||||
|         // * cannot modify disabled equipment | ||||
|         if(!GetLocalInt(OBJECT_SELF, "X2_JUST_A_DISABLEEQUIP")) | ||||
|         { | ||||
|             OpenInventory(oCreature, GetLastSpeaker()); | ||||
|         } | ||||
|         // * feedback as to why | ||||
|         else SendMessageToPCByStrRef(GetMaster(), 100895); | ||||
|         return; | ||||
|     } | ||||
|     else if(nMatch == ASSOCIATE_COMMAND_LEAVEPARTY) | ||||
|     { | ||||
|         object oMaster = GetMaster(); | ||||
|         string sTag = GetTag(GetArea(oMaster)); | ||||
|         // * henchman cannot be kicked out in the reaper realm | ||||
|         // * Followers can never be kicked out | ||||
|         if (sTag == "GatesofCania" || GetIsFollower(oCreature)) return; | ||||
|         if(GetIsObjectValid(oMaster)) | ||||
|         { | ||||
|             ai_ClearCreatureActions(); | ||||
|             if(GetAssociateType(oCreature) == ASSOCIATE_TYPE_HENCHMAN) | ||||
|             { | ||||
|                 string sConversation = GetLocalString(oCreature, "sConversation"); | ||||
|                 if (sConversation == "id1_plotgiver") | ||||
|                 { | ||||
|                     string sVariable = GetLocalString(oCreature, "sVariable"); | ||||
|                     object oDungeon = GetLocalObject(GetModule(), "oCurrentDungeon"); | ||||
|                     SetLocalInt(oDungeon, "b" + sVariable + "Gone", FALSE); | ||||
|                 } | ||||
|                 RemoveHenchman(oMaster); | ||||
|                 DestroyObject(oCreature); | ||||
|             } | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|     ExecuteScript("nw_ch_ac4", oCreature); | ||||
| } | ||||
| void ai_hen_id1_percept(object oCreature) | ||||
| { | ||||
|     // If henchman is dying and Player disappears then force a respawn of the henchman | ||||
|     if (GetIsHenchmanDying(oCreature)) | ||||
|     { | ||||
|         // The henchman must be removed otherwise their corpse will follow the player | ||||
|         object oOldMaster = GetMaster(); | ||||
|         object oPC = GetLastPerceived(); | ||||
|         int bVanish = GetLastPerceptionVanished(); | ||||
|         if(GetIsObjectValid(oPC) && bVanish) | ||||
|         { | ||||
|             if (oPC == oOldMaster) | ||||
|             { | ||||
|                 RemoveHenchman(oPC, oCreature); | ||||
|                 // Only in chapter 1 | ||||
|                 if(GetTag(GetModule()) == "x0_module1") | ||||
|                 { | ||||
|                     SetCommandable(TRUE); | ||||
|                     DoRespawn(oPC,  oCreature); // Should teleport henchman back | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     ExecuteScript("nw_ch_ac2", oCreature); | ||||
| } | ||||
| void ai_hen_id1_endcombat(object oCreature, int bFollower) | ||||
| { | ||||
|     if (ai_GetIsInCombat(oCreature)) | ||||
|     { | ||||
|         int nNum; | ||||
|         int nLine; | ||||
|         string sString; | ||||
|         int nCreature; | ||||
|         int bIntelligent; | ||||
|         int nRandom = d100(); | ||||
|         // chance of a oneliner | ||||
|         int nOnelinerPercentage = GetLocalInt(GetModule(), "nFlagCombatOneLinerFrequencyValue"); | ||||
|         if(nRandom <= nOnelinerPercentage) | ||||
|         { | ||||
|             string sCreature = GetLocalString(oCreature, "sVariable"); | ||||
|             // if the current creature is hostile towards PCs | ||||
|             if(sCreature != "") | ||||
|             { | ||||
|                 object oDungeon = GetLocalObject(GetModule(), "oCurrentDungeon"); | ||||
|                 if(GetIsReactionTypeHostile(GetFirstPC())) | ||||
|                 { | ||||
|                     nCreature = GetLocalInt(oDungeon, "n" + sCreature); | ||||
|                     bIntelligent = GetLocalInt(oDungeon, "bListCreature" + IntToString(nCreature) + "Intelligent"); | ||||
|                     if(bIntelligent) | ||||
|                     { | ||||
|                         nNum = GetLocalInt(GetModule(), "nLinesHostileNum"); | ||||
|                         nLine = Random(nNum) + 1; | ||||
|                         if(nLine > 0) | ||||
|                         { | ||||
|                             sString = GetLocalString(GetModule(), "sLinesHostile" + IntToString(nLine)); | ||||
|                             SpeakString(sString, TALKVOLUME_SHOUT); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     nCreature = GetLocalInt(oDungeon, "n" + sCreature); | ||||
|                     bIntelligent = GetLocalInt(oDungeon, "bListCreature" + IntToString(nCreature) + "Intelligent"); | ||||
|                     if(bIntelligent) | ||||
|                     { | ||||
|                         nNum = GetLocalInt(GetModule(), "nLinesAlliesNum"); | ||||
|                         nLine = Random(nNum) + 1; | ||||
|                         if (nLine > 0) | ||||
|                         { | ||||
|                             sString = GetLocalString(GetModule(), "sLinesAllies" + IntToString(nLine)); | ||||
|                             SpeakString(sString, TALKVOLUME_SHOUT); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     if(bFollower) ExecuteScript("nw_ch_ac3", oCreature); | ||||
|     else ExecuteScript("nw_c2_default3", oCreature); | ||||
| } | ||||
| void ai_hen_id1_castat(object oCreature) | ||||
| { | ||||
|     if(!GetLastSpellHarmful()) | ||||
|     { | ||||
|         int nSpell = GetLastSpell(); | ||||
|         if(nSpell == SPELL_RAISE_DEAD || nSpell  == SPELL_RESURRECTION) | ||||
|         { | ||||
|             object oCaster = GetLastSpellCaster(); | ||||
|             // Restore faction to neutral | ||||
|             SetStandardFactionReputation(STANDARD_FACTION_MERCHANT, 100, oCaster); | ||||
|             SetStandardFactionReputation(STANDARD_FACTION_COMMONER, 100, oCaster); | ||||
|             SetStandardFactionReputation(STANDARD_FACTION_DEFENDER, 100, oCaster); | ||||
|             ClearPersonalReputation(oCaster, oCreature); | ||||
|             AssignCommand(oCreature, SurrenderToEnemies()); | ||||
|             AssignCommand(oCreature, ai_ClearCreatureActions(TRUE)); | ||||
|             // Reset henchmen attack state - Oct 28 (BK) | ||||
|             ai_SetAIMode(oCreature, AI_MODE_DEFEND_MASTER, FALSE); | ||||
|             ai_SetAIMode(oCreature, AI_MODE_STAND_GROUND, FALSE); | ||||
|             ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); | ||||
|             ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE); | ||||
|             ai_SetAIMode(oCreature, AI_MODE_COMMANDED, FALSE); | ||||
|             // Oct 30 - If player previously hired this hench | ||||
|             // then just have them rejoin automatically | ||||
|             if(GetPlayerHasHired(oCaster, oCreature)) | ||||
|             { | ||||
|                 // Feb 11, 2004 - Jon: Don't fire the HireHenchman function if the | ||||
|                 // henchman is already oCaster's associate. Fixes a silly little problem | ||||
|                 // that occured when you try to raise a henchman who wasn't actually dead. | ||||
|                 if(GetMaster(oCreature)!= oCaster) HireHenchman(oCaster, oCreature, TRUE); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 string sFile = GetDialogFileToUse(oCaster); | ||||
|                 AssignCommand(oCaster, ActionStartConversation(oCreature, sFile)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     ExecuteScript("nw_ch_acb", oCreature); | ||||
| } | ||||
							
								
								
									
										46
									
								
								_module/nss/0e_m1_3_endround.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								_module/nss/0e_m1_3_endround.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_m1_3_endround | ||||
|  Original Script: m1_combanter_3 | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|   Monster OnCombatRoundEnd event script used in the original campaign | ||||
|   for monsters that may do a one liner during combat; | ||||
|  | ||||
|   Fires at the end of each combat round (6 seconds). | ||||
|   This will fire as long as oCreature is in combat (GetIsInCombat()). | ||||
|   This event starts counting once a combat action is started. | ||||
|   Every time a spell is cast it will queue another end combat round so haste with | ||||
|     two spells cast will fire this twice in one round. | ||||
|   It will also fire at the end of a hostile effect that stops actions i.e Stunned, Knockdown etc. | ||||
|   Action modes are also cleared prior to this event executing! | ||||
|   GetAttemptedAttackTarget() & GetAttemptedSpellTarget() also get cleared prior to this event. | ||||
|   This event can be canceled with ClearAllActions(TRUE) and SurrenderToEnemies. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     if(AI_DEBUG) ai_Debug("0e_m1_3_endround", "23", GetName(oCreature) + " ends combat round."); | ||||
|     // Action modes get cleared prior to each OnCombatRoundEnd! | ||||
|     // We do this to keep the action mode going. | ||||
|     int nActionMode = GetLocalInt(oCreature, AI_CURRENT_ACTION_MODE); | ||||
|     if(nActionMode > 0) | ||||
|     { | ||||
|         SetActionMode(oCreature, nActionMode, TRUE); | ||||
|         // We don't want to use up all of the Dwarven Defenders uses! | ||||
|         if(nActionMode == 12) IncrementRemainingFeatUses(oCreature, FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE); | ||||
|     } | ||||
|     if (ai_GetIsBusy(oCreature) || ai_Disabled(oCreature)) return; | ||||
|     if(Random(4) == 0) SpeakOneLinerConversation(); | ||||
|     if(ai_GetIsInCombat(oCreature)) ai_DoMonsterCombatRound(oCreature); | ||||
|     ai_SpellConcentrationCheck(oCreature); | ||||
|     if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) ai_DetermineSpecialBehavior(oCreature); | ||||
|     if(GetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT)) | ||||
|     { | ||||
|         SignalEvent(OBJECT_SELF, EventUserDefined(1003)); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										1972
									
								
								_module/nss/0e_nui.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1972
									
								
								_module/nss/0e_nui.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										700
									
								
								_module/nss/0e_nui_dm.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										700
									
								
								_module/nss/0e_nui_dm.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,700 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: 0e_nui_dm | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Menu event script | ||||
|     sEvent: close, click, mousedown, mouseup, watch (if bindwatch is set). | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_menus_dm" | ||||
| void ai_SetDMWidgetButtonToCheckbox(object oDM, int nButton, int nToken, string sElem); | ||||
| void ai_SetDMWAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem); | ||||
| void ai_SetDMAIAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem); | ||||
| void ai_SetDMAIAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem); | ||||
| void ai_RulePercDistInc(object oDM, object oModule, int nIncrement, int nToken); | ||||
| // Adds a spell to a json AI restricted spell list then returns jRules. | ||||
| // bRestrict = TRUE will add to the list FALSE will remove it from the list. | ||||
| json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE); | ||||
| // Adds a selected creature to the group. | ||||
| void ai_SelectToGroup(object oDM, string sElem); | ||||
| // Does a selected action for nGroup. | ||||
| void ai_DMSelectAction(object oDM, string sElem); | ||||
| // Changes if the group will run (nSpeed: 1) or walk (nSpeed: 0). | ||||
| void ai_DMChangeMoveSpeed(object oDM, string sElem, int nSpeed); | ||||
| void main() | ||||
| { | ||||
|     object oDM = NuiGetEventPlayer(); | ||||
|     int nToken  = NuiGetEventWindow(); | ||||
|     string sEvent = NuiGetEventType(); | ||||
|     string sElem  = NuiGetEventElement(); | ||||
|     int nIndex = NuiGetEventArrayIndex(); | ||||
|     string sWndId = NuiGetWindowId(oDM, nToken); | ||||
|     //if(AI_DEBUG) ai_Debug ("0e_nui", "58", "sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem + | ||||
|     //             " nToken: " + IntToString(nToken) + " oPC: " + GetName(oPC)); | ||||
|     //WriteTimestampedLogEntry("0e_nui, 58, sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem + | ||||
|     //             " nToken: " + IntToString(nToken) + " oDM: " + GetName(oDM)); | ||||
|     //************************************************************************** | ||||
|     string sName = ai_RemoveIllegalCharacters(GetName(oDM)); | ||||
|     // Watch to see if the window moves and save. | ||||
|     if(sElem == "window_geometry" && sEvent == "watch") | ||||
|     { | ||||
|         if(GetLocalInt(oDM, AI_NO_NUI_SAVE)) return; | ||||
|         SaveMenuToCampaignDb(oDM, nToken, sWndId); | ||||
|     } | ||||
|     //************************************************************************** | ||||
|     // Widget events. | ||||
|     if(sWndId == "dm" + AI_WIDGET_NUI) | ||||
|     { | ||||
|         //if(GetLocalInt(oDM, AI_NO_NUI_SAVE)) return; | ||||
|         if(sEvent == "click") | ||||
|         { | ||||
|             if(sElem == "btn_open_main") | ||||
|             { | ||||
|                 if(IsWindowClosed(oDM, "dm" + AI_COMMAND_NUI)) ai_CreateDMCommandNUI(oDM); | ||||
|                 IsWindowClosed(oDM, "dm" + AI_MAIN_NUI); | ||||
|             } | ||||
|             else if(sElem == "btn_camera") ai_SelectCameraView(oDM); | ||||
|             else if(sElem == "btn_inventory") ai_SelectOpenInventory(oDM); | ||||
|             else if(GetStringLeft(sElem, 13) == "btn_cmd_group") | ||||
|             { | ||||
|                 ai_DMSelectAction(oDM, sElem); | ||||
|             } | ||||
|             else if(GetStringLeft(sElem, 15) == "btn_exe_plugin_") ai_Plugin_Execute(oDM, sElem, TRUE); | ||||
|         } | ||||
|         else if(sEvent == "mousescroll") | ||||
|         { | ||||
|             float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y")); | ||||
|             if(nMouseScroll == 1.0) // Scroll up | ||||
|             { | ||||
|                 if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 1); | ||||
|             } | ||||
|             if(nMouseScroll == -1.0) // Scroll down | ||||
|             { | ||||
|                 if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 0); | ||||
|             } | ||||
|         } | ||||
|        else if(sEvent == "mousedown") | ||||
|         { | ||||
|             int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn")); | ||||
|             if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT) | ||||
|             { | ||||
|                 if(sElem == "btn_open_main") | ||||
|                 { | ||||
|                     if(IsWindowClosed(oDM, "dm" + AI_MAIN_NUI)) ai_CreateDMOptionsNUI(oDM); | ||||
|                 } | ||||
|                 else if(GetStringLeft(sElem, 13) == "btn_cmd_group") | ||||
|                 { | ||||
|                     ai_SelectToGroup(oDM, sElem); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else if(sWndId == "dm" + AI_COMMAND_NUI) | ||||
|     { | ||||
|         if(sEvent == "click") | ||||
|         { | ||||
|             if(sElem == "btn_widget_lock") | ||||
|             { | ||||
|                 if(ai_GetDMWidgetButton(oDM, BTN_DM_WIDGET_LOCK)) | ||||
|                 { | ||||
|                     ai_SendMessages(GetName(oDM) + " AI widget unlocked.", AI_COLOR_YELLOW, oDM); | ||||
|                     ai_SetDMWidgetButton(oDM, BTN_DM_WIDGET_LOCK, FALSE); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ai_SendMessages(GetName(oDM) + " AI widget locked.", AI_COLOR_YELLOW, oDM); | ||||
|                     ai_SetDMWidgetButton(oDM, BTN_DM_WIDGET_LOCK, TRUE); | ||||
|                 } | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI))); | ||||
|                 DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM)); | ||||
|             } | ||||
|             else if(sElem == "btn_main_menu") | ||||
|             { | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMOptionsNUI(oDM)); | ||||
|             } | ||||
|             else if(sElem == "btn_camera") ai_SelectCameraView(oDM); | ||||
|             else if(sElem == "btn_inventory") ai_SelectOpenInventory(oDM); | ||||
|             else if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMSelectAction(oDM, sElem); | ||||
|             else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oDM, sElem, 1); | ||||
|         } | ||||
|         else if(sEvent == "watch") | ||||
|         { | ||||
|             if(sElem == "chbx_cmd_group1_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP1, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_group2_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP2, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_group3_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP3, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_group4_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP4, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_group5_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP5, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_group6_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP6, nToken, sElem); | ||||
|             else if(sElem == "chbx_camera_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_CAMERA, nToken, sElem); | ||||
|             else if(sElem == "chbx_inventory_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_INVENTORY, nToken, sElem); | ||||
|             if(GetStringLeft(sElem, 12) == "chbx_plugin_" && GetStringRight(sElem, 6) == "_check") | ||||
|             { | ||||
|                 int nIndex = StringToInt(GetSubString(sElem, 12, 1)); | ||||
|                 json jPlugins = ai_GetCampaignDbJson("plugins", sName, AI_DM_TABLE); | ||||
|                 json jPlugin = JsonArrayGet(jPlugins, nIndex); | ||||
|                 int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem)); | ||||
|                 jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck)); | ||||
|                 jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin); | ||||
|                 ai_SetCampaignDbJson("plugins", jPlugins, sName, AI_DM_TABLE); | ||||
|             } | ||||
|             DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI))); | ||||
|             DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM)); | ||||
|         } | ||||
|         else if(sEvent == "mousescroll") | ||||
|         { | ||||
|             float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y")); | ||||
|             if(nMouseScroll == 1.0) // Scroll up | ||||
|             { | ||||
|                 if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 1); | ||||
|             } | ||||
|             if(nMouseScroll == -1.0) // Scroll down | ||||
|             { | ||||
|                 if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 0); | ||||
|             } | ||||
|         } | ||||
|         else if(sEvent == "mousedown") | ||||
|         { | ||||
|             int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn")); | ||||
|             if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT) | ||||
|             { | ||||
|                 if(GetStringLeft(sElem, 13) == "btn_cmd_group") | ||||
|                 { | ||||
|                     ai_SelectToGroup(oDM, sElem); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else if(sEvent == "mousescroll") | ||||
|         { | ||||
|             float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y")); | ||||
|             if(nMouseScroll == 1.0) // Scroll up | ||||
|             { | ||||
|             } | ||||
|             else if(nMouseScroll == -1.0) // Scroll down | ||||
|             { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     //************************************************************************** | ||||
|     // Main AI events. | ||||
|     if(sWndId == "dm" + AI_MAIN_NUI) | ||||
|     { | ||||
|         if(sEvent == "click") | ||||
|         { | ||||
|             if(sElem == "btn_plugin_manager") | ||||
|             { | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM)); | ||||
|             } | ||||
|             if(sElem == "btn_widget_manager") | ||||
|             { | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMWidgetManagerNUI(oDM)); | ||||
|             } | ||||
|         } | ||||
|         if(sEvent == "watch") | ||||
|         { | ||||
|             if(sElem == "txt_max_henchman") | ||||
|             { | ||||
|                 int nMaxHenchmen = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem))); | ||||
|                 if(nMaxHenchmen < 1) nMaxHenchmen = 1; | ||||
|                 if(nMaxHenchmen > 12) | ||||
|                 { | ||||
|                     nMaxHenchmen = 12; | ||||
|                     ai_SendMessages("The maximum henchmen for this mod is 12!", AI_COLOR_RED, oDM); | ||||
|                 } | ||||
|                 SetMaxHenchmen(nMaxHenchmen); | ||||
|                 json jRules = ai_GetCampaignDbJson("rules"); | ||||
|                 jRules = JsonObjectSet(jRules, AI_RULE_MAX_HENCHMAN, JsonInt(nMaxHenchmen)); | ||||
|                 ai_SetCampaignDbJson("rules", jRules); | ||||
|                 ai_SendMessages("Maximum henchmen has been changed to " + IntToString(nMaxHenchmen), AI_COLOR_YELLOW, oDM); | ||||
|             } | ||||
|             else if(sElem == "txt_ai_difficulty") | ||||
|             { | ||||
|                 int nChance = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem))); | ||||
|                 if(nChance < 0) nChance = 0; | ||||
|                 else if(nChance > 100) nChance = 100; | ||||
|                 SetLocalInt(GetModule(), AI_RULE_AI_DIFFICULTY, nChance); | ||||
|                 json jRules = ai_GetCampaignDbJson("rules"); | ||||
|                 jRules = JsonObjectSet(jRules, AI_RULE_AI_DIFFICULTY, JsonInt(nChance)); | ||||
|                 ai_SetCampaignDbJson("rules", jRules); | ||||
|             } | ||||
|             else if(sElem == "txt_perception_distance") | ||||
|             { | ||||
|                 float fDistance = StringToFloat(JsonGetString(NuiGetBind(oDM, nToken, sElem))); | ||||
|                 if(fDistance < 10.0) fDistance = 10.0; | ||||
|                 else if(fDistance > 60.0) fDistance = 60.0; | ||||
|                 SetLocalFloat(GetModule(), AI_RULE_PERCEPTION_DISTANCE, fDistance); | ||||
|                 json jRules = ai_GetCampaignDbJson("rules"); | ||||
|                 jRules = JsonObjectSet(jRules, AI_RULE_PERCEPTION_DISTANCE, JsonFloat(fDistance)); | ||||
|                 ai_SetCampaignDbJson("rules", jRules); | ||||
|             } | ||||
|             else if(sElem == "txt_inc_hp") | ||||
|             { | ||||
|                 int nNumber = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem))); | ||||
|                 if(nNumber < 0) nNumber = 0; | ||||
|                 else if(nNumber > 100) nNumber = 100; | ||||
|                 SetLocalInt(GetModule(), AI_INCREASE_MONSTERS_HP, nNumber); | ||||
|                 json jRules = ai_GetCampaignDbJson("rules"); | ||||
|                 jRules = JsonObjectSet(jRules, AI_INCREASE_MONSTERS_HP, JsonInt(nNumber)); | ||||
|                 ai_SetCampaignDbJson("rules", jRules); | ||||
|             } | ||||
|             else if(GetStringLeft(sElem, 4) == "chbx") | ||||
|             { | ||||
|                 object oModule = GetModule(); | ||||
|                 int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem)); | ||||
|                 json jRules = ai_GetCampaignDbJson("rules"); | ||||
|                 if(sElem == "chbx_moral_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_MORAL_CHECKS, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_MORAL_CHECKS, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_buff_monsters_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_BUFF_MONSTERS, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_buff_summons_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_PRESUMMON, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_PRESUMMON, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_ambush_monsters_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_AMBUSH, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_AMBUSH, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_companions_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_SUMMON_COMPANIONS, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_advanced_movement_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_ADVANCED_MOVEMENT, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_ADVANCED_MOVEMENT, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_ilr_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_ILR, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_ILR, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_umd_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_ALLOW_UMD, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_ALLOW_UMD, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_use_healingkits_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_HEALERSKITS, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_HEALERSKITS, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_perm_assoc_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_PERM_ASSOC, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_PERM_ASSOC, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_corpses_stay_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_CORPSES_STAY, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_CORPSES_STAY, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_wander_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_WANDER, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_CORPSES_STAY, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_open_doors_check") | ||||
|                 { | ||||
|                     SetLocalInt(oModule, AI_RULE_OPEN_DOORS, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_OPEN_DOORS, JsonInt(bCheck)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_party_scale_check") | ||||
|                 { | ||||
|                     if(bCheck) | ||||
|                     { | ||||
|                         SetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP, GetModuleXPScale()); | ||||
|                         ai_CheckXPPartyScale(oDM); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         SetModuleXPScale(GetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE)); | ||||
|                     } | ||||
|                     SetLocalInt(oModule, AI_RULE_PARTY_SCALE, bCheck); | ||||
|                     jRules = JsonObjectSet(jRules, AI_RULE_PARTY_SCALE, JsonInt(bCheck)); | ||||
|                     string sText = IntToString(GetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP)); | ||||
|                     NuiSetBind(oDM, nToken, "chbx_party_scale_tooltip", JsonString("  PEPS adjusts your XP based on party size from (" + sText + ").")); | ||||
|                     sText = IntToString(GetModuleXPScale()); | ||||
|                     NuiSetBind(oDM, nToken, "txt_xp_scale", JsonString(sText)); | ||||
|                 } | ||||
|                 else if(sElem == "chbx_darkness_check") | ||||
|                 { | ||||
|                     if(bCheck) | ||||
|                     { | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_DARKNESS); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, 159); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELLABILITY_AS_DARKNESS); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, 688); // WildShape_Darkness | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_DARKNESS, FALSE); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, 159, FALSE); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELLABILITY_AS_DARKNESS, FALSE); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, 688, FALSE); // WildShape_Darkness | ||||
|                     } | ||||
|                 } | ||||
|                 else if(sElem == "chbx_dispels_check") | ||||
|                 { | ||||
|                     if(bCheck) | ||||
|                     { | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_LESSER_DISPEL); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_DISPEL_MAGIC); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_GREATER_DISPELLING); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_MORDENKAINENS_DISJUNCTION); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_LESSER_DISPEL, FALSE); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_DISPEL_MAGIC, FALSE); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_GREATER_DISPELLING, FALSE); | ||||
|                         jRules = ai_AddRestrictedSpell(jRules, SPELL_MORDENKAINENS_DISJUNCTION, FALSE); | ||||
|                     } | ||||
|                 } | ||||
|                 else if(sElem == "chbx_timestop_check") | ||||
|                 { | ||||
|                     if(bCheck) jRules = ai_AddRestrictedSpell(jRules, SPELL_TIME_STOP); | ||||
|                     else jRules = ai_AddRestrictedSpell(jRules, SPELL_TIME_STOP, FALSE); | ||||
|                 } | ||||
|                 ai_SetCampaignDbJson("rules", jRules); | ||||
|             } | ||||
|         } | ||||
|         else if(sEvent == "mousescroll") | ||||
|         { | ||||
|             float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y")); | ||||
|             if(nMouseScroll == 1.0) // Scroll up | ||||
|             { | ||||
|                 // Follow range is only changed on non-pc's | ||||
|                 if(sElem == "lbl_perc_dist") ai_RulePercDistInc(oDM, GetModule(), 1, nToken); | ||||
|             } | ||||
|             else if(nMouseScroll == -1.0) // Scroll down | ||||
|             { | ||||
|                 // Follow range is only changed on non-pc's | ||||
|                 if(sElem == "lbl_perc_dist") ai_RulePercDistInc(oDM, GetModule(), -1, nToken); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     //************************************************************************** | ||||
|     // Plugins events. | ||||
|     if(sWndId == "dmai_plugin_nui") | ||||
|     { | ||||
|         string sName = ai_RemoveIllegalCharacters(GetName(oDM)); | ||||
|         json jPlugins = ai_GetCampaignDbJson("plugins"); | ||||
|         if(sEvent == "click") | ||||
|         { | ||||
|             if(sElem == "btn_load_plugins") | ||||
|             { | ||||
|                 string sScript = JsonGetString(NuiGetBind (oDM, nToken, "txt_plugin")); | ||||
|                 if(JsonGetType(JsonArrayGet(jPlugins, 0)) == JSON_TYPE_NULL) jPlugins = JsonArray(); | ||||
|                 jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_buffing"); | ||||
|                 jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_forcerest"); | ||||
|                 jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_henchmen"); | ||||
|                 jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_crafting"); | ||||
|                 jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_mod_set"); | ||||
|                 jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_debug"); | ||||
|                 jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_test"); | ||||
|                 ai_SetCampaignDbJson("plugins", jPlugins); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM)); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI))); | ||||
|                 DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM)); | ||||
|             } | ||||
|             if(sElem == "btn_check_plugins") | ||||
|             { | ||||
|                 int nIndex; | ||||
|                 json jPlugin = JsonArrayGet(jPlugins, nIndex); | ||||
|                 while(JsonGetType(jPlugin) != JSON_TYPE_NULL) | ||||
|                 { | ||||
|                     jPlugin = JsonArraySet(jPlugin, 1, JsonBool(TRUE)); | ||||
|                     jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin); | ||||
|                     jPlugin = JsonArrayGet(jPlugins, ++nIndex); | ||||
|                 } | ||||
|                 ai_SetCampaignDbJson("plugins", jPlugins); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM)); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI))); | ||||
|                 DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM)); | ||||
|             } | ||||
|             if(sElem == "btn_clear_plugins") | ||||
|             { | ||||
|                 int nIndex; | ||||
|                 json jPlugin = JsonArrayGet(jPlugins, nIndex); | ||||
|                 while(JsonGetType(jPlugin) != JSON_TYPE_NULL) | ||||
|                 { | ||||
|                     jPlugin = JsonArraySet(jPlugin, 1, JsonBool(FALSE)); | ||||
|                     jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin); | ||||
|                     jPlugin = JsonArrayGet(jPlugins, ++nIndex); | ||||
|                 } | ||||
|                 ai_SetCampaignDbJson("plugins", jPlugins); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM)); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI))); | ||||
|                 DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM)); | ||||
|             } | ||||
|             else if(sElem == "btn_add_plugin") | ||||
|             { | ||||
|                 string sScript = JsonGetString(NuiGetBind (oDM, nToken, "txt_plugin")); | ||||
|                 if(JsonGetType(JsonArrayGet(jPlugins, 0)) == JSON_TYPE_NULL) jPlugins = JsonArray(); | ||||
|                 jPlugins = ai_Plugin_Add(oDM, jPlugins, sScript); | ||||
|                 ai_SetCampaignDbJson("plugins", jPlugins); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM)); | ||||
|             } | ||||
|             else if(GetStringLeft(sElem, 18) == "btn_remove_plugin_") | ||||
|             { | ||||
|                 int nIndex = StringToInt(GetStringRight(sElem, 1)); | ||||
|                 jPlugins = JsonArrayDel(jPlugins, nIndex); | ||||
|                 ai_SetCampaignDbJson("plugins", jPlugins); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM)); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI))); | ||||
|                 DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM)); | ||||
|             } | ||||
|             else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oDM, sElem, 2); | ||||
|         } | ||||
|         else if(sEvent == "watch") | ||||
|         { | ||||
|             if(GetStringLeft(sElem, 12) == "chbx_plugin_" && GetStringRight(sElem, 6) == "_check") | ||||
|             { | ||||
|                 int nIndex = StringToInt(GetSubString(sElem, 12, 1)); | ||||
|                 json jPlugin = JsonArrayGet(jPlugins, nIndex); | ||||
|                 int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem)); | ||||
|                 jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck)); | ||||
|                 jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin); | ||||
|                 ai_SetCampaignDbJson("plugins", jPlugins); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI))); | ||||
|                 DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     if(sWndId == "dm_widget_manager_nui") | ||||
|     { | ||||
|         //SendMessageToDM(oDM, "sEvent: " + sEvent + " sElem: " + sElem); | ||||
|         if(sEvent == "click") | ||||
|         { | ||||
|             if(sElem == "btn_clear_buttons") | ||||
|             { | ||||
|                 object oModule = GetModule(); | ||||
|                 SetLocalInt(oModule, sDMWidgetAccessVarname, 0); | ||||
|                 SetLocalInt(oModule, sDMAIAccessVarname, 0); | ||||
|                 json jRules = ai_GetCampaignDbJson("rules"); | ||||
|                 jRules = JsonObjectSet(jRules, sDMWidgetAccessVarname, JsonInt(0)); | ||||
|                 jRules = JsonObjectSet(jRules, sDMAIAccessVarname, JsonInt(0)); | ||||
|                 ai_SetCampaignDbJson("rules", jRules); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMWidgetManagerNUI(oDM)); | ||||
|                 return; | ||||
|             } | ||||
|             else if(sElem == "btn_check_buttons") | ||||
|             { | ||||
|                 object oModule = GetModule(); | ||||
|                 SetLocalInt(oModule, sDMWidgetAccessVarname, 7340028); | ||||
|                 SetLocalInt(oModule, sDMAIAccessVarname, 203423743); | ||||
|                 json jRules = ai_GetCampaignDbJson("rules"); | ||||
|                 jRules = JsonObjectSet(jRules, sDMWidgetAccessVarname, JsonInt(7340028)); | ||||
|                 jRules = JsonObjectSet(jRules, sDMAIAccessVarname, JsonInt(203423743)); | ||||
|                 ai_SetCampaignDbJson("rules", jRules); | ||||
|                 DelayCommand(0.0, NuiDestroy(oDM, nToken)); | ||||
|                 DelayCommand(0.1, ai_CreateDMWidgetManagerNUI(oDM)); | ||||
|                 return; | ||||
|             } | ||||
|             SetLocalInt(oDM, "CHBX_SKIP", TRUE); | ||||
|             DelayCommand(2.0, DeleteLocalInt(oDM, "CHBX_SKIP")); | ||||
|             if(sElem == "btn_cmd_action") NuiSetBind(oDM, nToken, "chbx_cmd_action_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_ACTION))); | ||||
|             else if(sElem == "btn_cmd_guard") NuiSetBind(oDM, nToken, "chbx_cmd_guard_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_GUARD))); | ||||
|             else if(sElem == "btn_cmd_hold") NuiSetBind(oDM, nToken, "chbx_cmd_hold_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_HOLD))); | ||||
|             else if(sElem == "btn_cmd_attack") NuiSetBind(oDM, nToken, "chbx_cmd_attack_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_ATTACK))); | ||||
|             else if(sElem == "btn_cmd_follow") NuiSetBind(oDM, nToken, "chbx_cmd_follow_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_FOLLOW))); | ||||
|             else if(sElem == "btn_follow_target") NuiSetBind(oDM, nToken, "chbx_follow_target_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_FOLLOW_TARGET))); | ||||
|             else if(sElem == "btn_cmd_search") NuiSetBind(oDM, nToken, "chbx_cmd_search_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_SEARCH))); | ||||
|             else if(sElem == "btn_cmd_stealth") NuiSetBind(oDM, nToken, "chbx_cmd_stealth_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_STEALTH))); | ||||
|             else if(sElem == "btn_cmd_ai_script") NuiSetBind(oDM, nToken, "chbx_cmd_ai_script_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_AI_SCRIPT))); | ||||
|             else if(sElem == "btn_cmd_place_trap") NuiSetBind(oDM, nToken, "chbx_cmd_place_trap_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_PLACE_TRAP))); | ||||
|             else if(sElem == "btn_quick_widget") NuiSetBind(oDM, nToken, "chbx_quick_widget_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_SPELL_WIDGET))); | ||||
|             else if(sElem == "btn_spell_memorize") NuiSetBind(oDM, nToken, "chbx_spell_memorize_check", JsonBool(!ai_GetDMWAccessButton(BTN_DM_CMD_MEMORIZE))); | ||||
|             else if(sElem == "btn_buff_short") NuiSetBind(oDM, nToken, "chbx_buff_short_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_SHORT))); | ||||
|             else if(sElem == "btn_buff_long") NuiSetBind(oDM, nToken, "chbx_buff_long_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_LONG))); | ||||
|             else if(sElem == "btn_buff_all") NuiSetBind(oDM, nToken, "chbx_buff_all_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_ALL))); | ||||
|             else if(sElem == "btn_buff_rest") NuiSetBind(oDM, nToken, "chbx_buff_rest_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_REST))); | ||||
|             else if(sElem == "btn_jump_to") NuiSetBind(oDM, nToken, "chbx_jump_to_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_JUMP_TO))); | ||||
|             else if(sElem == "btn_ghost_mode") NuiSetBind(oDM, nToken, "chbx_ghost_mode_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_GHOST_MODE))); | ||||
|             else if(sElem == "btn_camera") NuiSetBind(oDM, nToken, "chbx_camera_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_CAMERA))); | ||||
|             else if(sElem == "btn_inventory") NuiSetBind(oDM, nToken, "chbx_inventory_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_INVENTORY))); | ||||
|             else if(sElem == "btn_familiar") NuiSetBind(oDM, nToken, "chbx_familiar_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_FAMILIAR))); | ||||
|             else if(sElem == "btn_companion") NuiSetBind(oDM, nToken, "chbx_companion_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_COMPANION))); | ||||
|             else if(sElem == "btn_ai") NuiSetBind(oDM, nToken, "chbx_ai_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_FOR_PC))); | ||||
|             else if(sElem == "btn_quiet") NuiSetBind(oDM, nToken, "chbx_quiet_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_REDUCE_SPEECH))); | ||||
|             else if(sElem == "btn_ranged") NuiSetBind(oDM, nToken, "chbx_ranged_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_USE_RANGED))); | ||||
|             else if(sElem == "btn_search") NuiSetBind(oDM, nToken, "chbx_search_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_USE_SEARCH))); | ||||
|             else if(sElem == "btn_stealth") NuiSetBind(oDM, nToken, "chbx_stealth_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_USE_STEALTH))); | ||||
|             else if(sElem == "btn_open_door") NuiSetBind(oDM, nToken, "chbx_open_door_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_OPEN_DOORS))); | ||||
|             else if(sElem == "btn_traps") NuiSetBind(oDM, nToken, "chbx_traps_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_REMOVE_TRAPS))); | ||||
|             else if(sElem == "btn_pick_locks") NuiSetBind(oDM, nToken, "chbx_pick_locks_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_PICK_LOCKS))); | ||||
|             else if(sElem == "btn_bash_locks") NuiSetBind(oDM, nToken, "chbx_bash_locks_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_BASH_LOCKS))); | ||||
|             else if(sElem == "btn_magic_level") NuiSetBind(oDM, nToken, "chbx_magic_level_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_MAGIC_LEVEL))); | ||||
|             else if(sElem == "btn_spontaneous") NuiSetBind(oDM, nToken, "chbx_spontaneous_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_NO_SPONTANEOUS))); | ||||
|             else if(sElem == "btn_magic") NuiSetBind(oDM, nToken, "chbx_magic_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_USE))); | ||||
|             else if(sElem == "btn_magic_items") NuiSetBind(oDM, nToken, "chbx_magic_items_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_ITEM_USE))); | ||||
|             else if(sElem == "btn_def_magic") NuiSetBind(oDM, nToken, "chbx_def_magic_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_DEF_MAGIC_USE))); | ||||
|             else if(sElem == "btn_off_magic") NuiSetBind(oDM, nToken, "chbx_off_magic_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_OFF_MAGIC_USE))); | ||||
|             else if(sElem == "btn_heal_out") NuiSetBind(oDM, nToken, "chbx_heal_out_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_HEAL_OUT))); | ||||
|             else if(sElem == "btn_heal_in") NuiSetBind(oDM, nToken, "chbx_heal_in_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_HEAL_IN))); | ||||
|             else if(sElem == "btn_heals_onoff") NuiSetBind(oDM, nToken, "chbx_heals_onoff_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_STOP_SELF_HEALING))); | ||||
|             else if(sElem == "btn_healp_onoff") NuiSetBind(oDM, nToken, "chbx_healp_onoff_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_STOP_PARTY_HEALING))); | ||||
|             else if(sElem == "btn_loot") NuiSetBind(oDM, nToken, "chbx_loot_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_LOOT))); | ||||
|             else if(sElem == "btn_ignore_assoc") NuiSetBind(oDM, nToken, "chbx_ignore_assoc_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_IGNORE_ASSOCIATES))); | ||||
|             else if(sElem == "btn_ignore_traps") NuiSetBind(oDM, nToken, "chbx_ignore_traps_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_IGNORE_TRAPS))); | ||||
|             else if(sElem == "btn_perc_range") NuiSetBind(oDM, nToken, "chbx_perc_range_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_PERC_RANGE))); | ||||
|         } | ||||
|         if(sEvent == "watch") | ||||
|         { | ||||
|             if(GetLocalInt(oDM, "CHBX_SKIP")) return; | ||||
|             if(sElem == "chbx_cmd_action_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_ACTION, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_guard_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_GUARD, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_hold_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_HOLD, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_attack_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_ATTACK, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_follow_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_FOLLOW, nToken, sElem); | ||||
|             else if(sElem == "chbx_follow_target_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_FOLLOW_TARGET, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_search_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_SEARCH, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_stealth_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_STEALTH, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_ai_script_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_AI_SCRIPT, nToken, sElem); | ||||
|             else if(sElem == "chbx_cmd_place_trap_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_PLACE_TRAP, nToken, sElem); | ||||
|             else if(sElem == "chbx_quick_widget_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_SPELL_WIDGET, nToken, sElem); | ||||
|             else if(sElem == "chbx_spell_memorize_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_DM_CMD_MEMORIZE, nToken, sElem); | ||||
|             else if(sElem == "chbx_buff_short_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_SHORT, nToken, sElem); | ||||
|             else if(sElem == "chbx_buff_long_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_LONG, nToken, sElem); | ||||
|             else if(sElem == "chbx_buff_all_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_ALL, nToken, sElem); | ||||
|             else if(sElem == "chbx_buff_rest_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_REST, nToken, sElem); | ||||
|             else if(sElem == "chbx_jump_to_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_JUMP_TO, nToken, sElem); | ||||
|             else if(sElem == "chbx_ghost_mode_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_GHOST_MODE, nToken, sElem); | ||||
|             else if(sElem == "chbx_camera_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_CAMERA, nToken, sElem); | ||||
|             else if(sElem == "chbx_inventory_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_INVENTORY, nToken, sElem); | ||||
|             else if(sElem == "chbx_familiar_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_FAMILIAR, nToken, sElem); | ||||
|             else if(sElem == "chbx_companion_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_COMPANION, nToken, sElem); | ||||
|             else if(sElem == "chbx_ai_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_FOR_PC, nToken, sElem); | ||||
|             else if(sElem == "chbx_quiet_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_REDUCE_SPEECH, nToken, sElem); | ||||
|             else if(sElem == "chbx_ranged_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_USE_RANGED, nToken, sElem); | ||||
|             else if(sElem == "chbx_search_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_USE_SEARCH, nToken, sElem); | ||||
|             else if(sElem == "chbx_stealth_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_USE_STEALTH, nToken, sElem); | ||||
|             else if(sElem == "chbx_open_door_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_OPEN_DOORS, nToken, sElem); | ||||
|             else if(sElem == "chbx_traps_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_REMOVE_TRAPS, nToken, sElem); | ||||
|             else if(sElem == "chbx_pick_locks_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_PICK_LOCKS, nToken, sElem); | ||||
|             else if(sElem == "chbx_bash_locks_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_BASH_LOCKS, nToken, sElem); | ||||
|             else if(sElem == "chbx_magic_level_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_MAGIC_LEVEL, nToken, sElem); | ||||
|             else if(sElem == "chbx_spontaneous_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_NO_SPONTANEOUS, nToken, sElem); | ||||
|             else if(sElem == "chbx_magic_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_NO_MAGIC_USE, nToken, sElem); | ||||
|             else if(sElem == "chbx_magic_items_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_NO_MAGIC_ITEM_USE, nToken, sElem); | ||||
|             else if(sElem == "chbx_def_magic_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_DEF_MAGIC_USE, nToken, sElem); | ||||
|             else if(sElem == "chbx_off_magic_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_OFF_MAGIC_USE, nToken, sElem); | ||||
|             else if(sElem == "chbx_heal_out_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_HEAL_OUT, nToken, sElem); | ||||
|             else if(sElem == "chbx_heal_in_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_HEAL_IN, nToken, sElem); | ||||
|             else if(sElem == "chbx_heals_onoff_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_STOP_SELF_HEALING, nToken, sElem); | ||||
|             else if(sElem == "chbx_healp_onoff_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_STOP_PARTY_HEALING, nToken, sElem); | ||||
|             else if(sElem == "chbx_loot_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_LOOT, nToken, sElem); | ||||
|             else if(sElem == "chbx_ignore_assoc_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_IGNORE_ASSOCIATES, nToken, sElem); | ||||
|             else if(sElem == "chbx_ignore_traps_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_IGNORE_TRAPS, nToken, sElem); | ||||
|             else if(sElem == "chbx_perc_range_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_PERC_RANGE, nToken, sElem); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| void ai_SetDMWidgetButtonToCheckbox(object oDM, int nButton, int nToken, string sElem) | ||||
| { | ||||
|     int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem)); | ||||
|     ai_SetDMWidgetButton(oDM, nButton, bCheck); | ||||
| } | ||||
| void ai_SetDMWAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem) | ||||
| { | ||||
|     int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem)); | ||||
|     ai_SetDMWAccessButton(nButton, bCheck); | ||||
| } | ||||
| void ai_SetDMAIAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem) | ||||
| { | ||||
|     int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem)); | ||||
|     ai_SetDMAIAccessButton(nButton, bCheck); | ||||
| } | ||||
| void ai_RulePercDistInc(object oDM, object oModule, int nIncrement, int nToken) | ||||
| { | ||||
|     int nAdjustment = GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE) + nIncrement; | ||||
|     if(nAdjustment < 8 || nAdjustment > 11) return; | ||||
|     SetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE, nAdjustment); | ||||
|     string sText; | ||||
|     if(nAdjustment == 8) sText = " Monster perception: Short [10 Sight / 10 Listen]"; | ||||
|     else if(nAdjustment == 9) sText = " Monster perception: Medium [20 Sight / 20 Listen]"; | ||||
|     else if(nAdjustment == 10) sText = " Monster perception: Long [35 Sight / 20 Listen]"; | ||||
|     else sText = " Monster perception: Default [Monster's default values]"; | ||||
|     NuiSetBind(oDM, nToken, "lbl_perc_dist_label", JsonString(sText)); | ||||
|     json jRules = ai_GetCampaignDbJson("rules"); | ||||
|     jRules = JsonObjectSet(jRules, AI_RULE_MON_PERC_DISTANCE, JsonInt(nAdjustment)); | ||||
|     ai_SetCampaignDbJson("rules", jRules); | ||||
| } | ||||
| json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE) | ||||
| { | ||||
|     object oModule = GetModule(); | ||||
|     json jRSpells = GetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS); | ||||
|     int nIndex, nMaxIndex = JsonGetLength(jRSpells); | ||||
|     if(bRestrict) | ||||
|     { | ||||
|         while(nIndex < nMaxIndex) | ||||
|         { | ||||
|             if(JsonGetInt(JsonArrayGet(jRSpells, nIndex)) == nSpell) return jRules; | ||||
|             nIndex++; | ||||
|         } | ||||
|         jRSpells = JsonArrayInsert(jRSpells, JsonInt(nSpell)); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         while(nIndex < nMaxIndex) | ||||
|         { | ||||
|             if(JsonGetInt(JsonArrayGet(jRSpells, nIndex)) == nSpell) | ||||
|             { | ||||
|                 jRSpells = JsonArrayDel(jRSpells, nIndex); | ||||
|                 break; | ||||
|             } | ||||
|             nIndex++; | ||||
|         } | ||||
|     } | ||||
|     SetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS, jRSpells); | ||||
|     return JsonObjectSet(jRules, AI_RULE_RESTRICTED_SPELLS, jRSpells); | ||||
| } | ||||
| void ai_SelectToGroup(object oDM, string sElem) | ||||
| { | ||||
|     string sGroup = GetStringRight(sElem, 1); | ||||
|     SetLocalString(oDM, AI_TARGET_MODE, "DM_SELECT_GROUP" + sGroup); | ||||
|     ai_SendMessages("Select a creature to add to group " + sGroup + ". Selecting yourself will clear group1.", AI_COLOR_YELLOW, oDM); | ||||
|     EnterTargetingMode(oDM, OBJECT_TYPE_CREATURE, MOUSECURSOR_PICKUP, MOUSECURSOR_PICKUP_DOWN); | ||||
| } | ||||
| void ai_DMSelectAction(object oDM, string sElem) | ||||
| { | ||||
|     string sGroup = GetStringRight(sElem, 1); | ||||
|     SetLocalString(oDM, AI_TARGET_MODE, "DM_ACTION_GROUP" + sGroup); | ||||
|     ai_SendMessages(GetName(oDM) + " select an action for group" + sGroup + ".", AI_COLOR_YELLOW, oDM); | ||||
|     EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
| } | ||||
| void ai_DMChangeMoveSpeed(object oDM, string sElem, int nSpeed) | ||||
| { | ||||
|     string sGroup = GetStringRight(sElem, 1); | ||||
|     json jGroup = GetLocalJson(oDM, "DM_GROUP" + sGroup); | ||||
|     if(JsonGetType(jGroup) == JSON_TYPE_NULL) | ||||
|     { | ||||
|         ai_SendMessages("This group does not contain any creatures!", AI_COLOR_RED, oDM); | ||||
|         return; | ||||
|     } | ||||
|     jGroup = JsonArraySet(jGroup, 0, JsonInt(nSpeed)); | ||||
|     SetLocalJson(oDM, "DM_GROUP" + sGroup, jGroup); | ||||
|     object oLeader = GetObjectByUUID(JsonGetString(JsonArrayGet(jGroup, 1))); | ||||
|     string sName = GetName(oLeader); | ||||
|     string sText = "  " + sName + "'s group"; | ||||
|     if(nSpeed == 0) sText += " [Walk]"; | ||||
|     else sText += " [Run]"; | ||||
|     NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText)); | ||||
|     NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText)); | ||||
| } | ||||
							
								
								
									
										23
									
								
								_module/nss/0e_onclientload.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								_module/nss/0e_onclientload.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script: 0e_onclientload | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|   Monster OnClientLoad script; | ||||
|   This will fire when the client is loading. | ||||
|  | ||||
|   If you have your own OnClientLoad event script just take the below | ||||
|   script lines and add them into your OnClientLoad script. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_menus_dm" | ||||
| #include "0i_module" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // This can be moved to the OnClientLoad script event of your module. | ||||
|     if(ai_GetIsCharacter(oCreature)) ai_CheckPCStart(oCreature); | ||||
|     // If this is a server you can add this as well. | ||||
|     else if(AI_SERVER && (GetIsDM(oCreature) || GetIsPlayerDM(oCreature))) | ||||
|     { | ||||
|         ai_CheckPCStart(oCreature); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										154
									
								
								_module/nss/0e_player_target.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								_module/nss/0e_player_target.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,154 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: 0e_player_target | ||||
|  Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  OnPlayerTarget event script | ||||
|     Used to allow player targeting while passing any module player targeting | ||||
|     script through to work as intended. | ||||
|  | ||||
|     We Use a string variable upon the player using the targeting mode to define the | ||||
|     action of the target. | ||||
|     AI_TARGET_MODE is the constant used. | ||||
|     AI_TARGET_ASSOCIATE is the associate that triggered the target mode. | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_player_target" | ||||
| void main() | ||||
| { | ||||
|     object oPC = GetLastPlayerToSelectTarget(); | ||||
|     // Get any plugin target scripts and run it instead of this one. | ||||
|     string sPluginTargetScript = GetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT); | ||||
|     if(sPluginTargetScript != "") | ||||
|     { | ||||
|         DeleteLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT); | ||||
|         ExecuteScript(sPluginTargetScript, oPC); | ||||
|         // Remove the plugin script as it must be set each time the plugin uses the target event. | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // Get the targeting mode data | ||||
|         object oTarget = GetTargetingModeSelectedObject(); | ||||
|         vector vTarget = GetTargetingModeSelectedPosition(); | ||||
|         location lLocation = Location(GetArea(oPC), vTarget, GetFacing(oPC)); | ||||
|         object oAssociate = GetLocalObject(oPC, AI_TARGET_ASSOCIATE); | ||||
|         string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE); | ||||
|         // ********************* Exiting Target Actions ************************ | ||||
|         // If the user manually exited targeting mode without selecting a target, return | ||||
|         if(!GetIsObjectValid(oTarget) && vTarget == Vector()) | ||||
|         { | ||||
|             if(sTargetMode == "ASSOCIATE_ACTION_ALL") | ||||
|             { | ||||
|                 ai_SendMessages("You have exited selecting an action for the party.", AI_COLOR_YELLOW, oPC); | ||||
|                 if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") | ||||
|                 { | ||||
|                     if(GetLocalInt(oPC, sGhostModeVarname)) ai_OriginalRemoveAllActionMode(oPC); | ||||
|                 } | ||||
|                 else ai_RemoveAllActionMode(oPC); | ||||
|             } | ||||
|             else if(sTargetMode == "ASSOCIATE_ACTION") | ||||
|             { | ||||
|                 ai_SendMessages("You have exited selecting an action for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC); | ||||
|                 if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") | ||||
|                 { | ||||
|                     if(GetLocalInt(oPC, sGhostModeVarname)) | ||||
|                     { | ||||
|                         ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); | ||||
|                         DeleteLocalInt(oAssociate, sGhostModeVarname); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, FALSE); | ||||
|                     if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) && !ai_GetAIMode(oPC, AI_MODE_GHOST) && | ||||
|                        GetLocalInt(oAssociate, sGhostModeVarname)) | ||||
|                     { | ||||
|  | ||||
|                         ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); | ||||
|                         DeleteLocalInt(oAssociate, sGhostModeVarname); | ||||
|                     } | ||||
|                     ExecuteScript("nw_ch_ac1", oAssociate); | ||||
|                 } | ||||
|             } | ||||
|             else if(sTargetMode == "ASSOCIATE_GET_TRAP") | ||||
|             { | ||||
|                 ai_SendMessages(GetName(oAssociate) + " has exited selecing a trap!", AI_COLOR_YELLOW, oPC); | ||||
|             } | ||||
|             else if(sTargetMode == "ASSOCIATE_PLACE_TRAP") | ||||
|             { | ||||
|                 ai_SendMessages(GetName(oAssociate) + " has exited placing the trap!", AI_COLOR_YELLOW, oPC); | ||||
|             } | ||||
|             else if(sTargetMode == "DM_SELECT_CAMERA_VIEW") | ||||
|             { | ||||
|                 AttachCamera(oPC, oPC); | ||||
|                 ai_SendMessages(GetName(oPC) + " has defaulted camera view back to the player!", AI_COLOR_YELLOW, oPC); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         // ************************* Targeted Actions ************************** | ||||
|         else | ||||
|         { | ||||
|             // This action makes an associates move to vTarget. | ||||
|             if(sTargetMode == "ASSOCIATE_ACTION_ALL") | ||||
|             { | ||||
|                 if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") | ||||
|                 { | ||||
|                     ai_OriginalActionAllAssociates(oPC, oTarget, lLocation); | ||||
|                 } | ||||
|                 else ai_ActionAllAssociates(oPC, oTarget, lLocation); | ||||
|             } | ||||
|             else if(sTargetMode == "ASSOCIATE_ACTION") | ||||
|             { | ||||
|                 if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "") | ||||
|                 { | ||||
|                     AssignCommand(oAssociate, ai_OriginalActionAssociate(oPC, oTarget, lLocation)); | ||||
|                 } | ||||
|                 else AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation)); | ||||
|             } | ||||
|             else if(sTargetMode == "ASSOCIATE_FOLLOW_TARGET") ai_SelectFollowTarget(oPC, oAssociate, oTarget); | ||||
|             else if(sTargetMode == "ASSOCIATE_GET_TRAP") ai_SelectTrap(oPC, oAssociate, oTarget); | ||||
|             else if(sTargetMode == "ASSOCIATE_PLACE_TRAP") AssignCommand(oAssociate, ai_PlaceTrap(oPC, lLocation)); | ||||
|             else if(sTargetMode == "ASSOCIATE_USE_ITEM") | ||||
|             { | ||||
|                 if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID; | ||||
|                 ai_UseWidgetItem(oPC, oAssociate, oTarget, lLocation); | ||||
|                 DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); | ||||
|             } | ||||
|             else if(sTargetMode == "ASSOCIATE_USE_FEAT") | ||||
|             { | ||||
|                 if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID; | ||||
|                 ai_UseWidgetFeat(oPC, oAssociate, oTarget, lLocation); | ||||
|                 DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); | ||||
|             } | ||||
|             else if(sTargetMode == "ASSOCIATE_CAST_SPELL") | ||||
|             { | ||||
|                 if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID; | ||||
|                 ai_CastWidgetSpell(oPC, oAssociate, oTarget, lLocation); | ||||
|                 DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); | ||||
|             } | ||||
|             else if(sTargetMode == "DM_SELECT_CAMERA_VIEW") | ||||
|             { | ||||
|                 AttachCamera(oPC, oTarget); | ||||
|                 ai_SendMessages(GetName(oPC) + " has changed the camera view to " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC); | ||||
|             } | ||||
|             else if(sTargetMode == "DM_SELECT_OPEN_INVENTORY") | ||||
|             { | ||||
|                 if(LineOfSightObject(oPC, oTarget)) | ||||
|                 { | ||||
|                     OpenInventory(oTarget, oPC); | ||||
|                     ai_SendMessages("You have opened the inventory of "+ GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC); | ||||
|                 } | ||||
|                 else ai_SendMessages(GetName(oTarget) + " is not in your line of sight!", AI_COLOR_YELLOW, oPC); | ||||
|             } | ||||
|             else if(GetStringLeft(sTargetMode, 15) == "DM_SELECT_GROUP") | ||||
|             { | ||||
|                 ai_AddToGroup(oPC, oTarget, sTargetMode); | ||||
|             } | ||||
|             else if(GetStringLeft(sTargetMode, 15) == "DM_ACTION_GROUP") | ||||
|             { | ||||
|                 ai_DMAction(oPC, oTarget, lLocation, sTargetMode); | ||||
|             } | ||||
|             // Get saved module player target script and execute it for pass through compatibility. | ||||
|             string sModuleTargetScript = GetLocalString(GetModule(), AI_MODULE_TARGET_EVENT); | ||||
|             ExecuteScript(sModuleTargetScript); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										78
									
								
								_module/nss/0e_prc_ch_events.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								_module/nss/0e_prc_ch_events.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0e_prc_ch_events | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|     associate event handler while using the PRC. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| #include "x0_i0_assoc" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     int nEvent = GetCurrentlyRunningEvent(); | ||||
|     //WriteTimestampedLogEntry("0e_prc_ch_events [13] " + GetName(oCreature) + " nEvent: " + IntToString(nEvent)); | ||||
|     switch (nEvent) | ||||
|     { | ||||
|         case EVENT_SCRIPT_CREATURE_ON_HEARTBEAT: | ||||
|         { | ||||
|             if(GetLocalInt(oCreature, "CohortID")) ExecuteScript("prc_ai_coh_hb"); | ||||
|             ExecuteScript("nw_ch_ac1", oCreature); | ||||
|             ExecuteScript("prc_npc_hb", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_NOTICE: | ||||
|         { | ||||
|             ExecuteScript("nw_ch_ac2", oCreature); | ||||
|             ExecuteScript("prc_npc_percep", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_DIALOGUE: | ||||
|         { | ||||
|             //if(GetLocalInt(oCreature, "CohortID")) ExecuteScript("prc_ai_coh_conv"); | ||||
|             ExecuteScript("nw_ch_ac4", oCreature); | ||||
|             //ExecuteScript("prc_npc_conv", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED: | ||||
|         { | ||||
|             ExecuteScript("nw_ch_ac5", oCreature); | ||||
|             ExecuteScript("prc_npc_physatt", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_DAMAGED: | ||||
|         { | ||||
|             ExecuteScript("nw_ch_ac6", oCreature); | ||||
|             ExecuteScript("prc_npc_damaged", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT: | ||||
|         { | ||||
|             ExecuteScript("nw_ch_acb", oCreature); | ||||
|             ExecuteScript("prc_npc_spellat", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND: | ||||
|         { | ||||
|             ExecuteScript("nw_ch_ac3", oCreature); | ||||
|             ExecuteScript("prc_npc_combat", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR: | ||||
|         { | ||||
|             ExecuteScript("nw_ch_ace", oCreature); | ||||
|             ExecuteScript("prc_npc_blocked", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_RESTED: | ||||
|         { | ||||
|             ExecuteScript("nw_ch_aca", oCreature); | ||||
|             //ExecuteScript("prc_npc_rested", oCreature); | ||||
|             break; | ||||
|         } | ||||
|         case EVENT_SCRIPT_CREATURE_ON_DISTURBED: | ||||
|         { | ||||
|             ExecuteScript("nw_ch_ac8", oCreature); | ||||
|             ExecuteScript("prc_npc_disturb", oCreature); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										2325
									
								
								_module/nss/0i_actions.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2325
									
								
								_module/nss/0i_actions.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2192
									
								
								_module/nss/0i_associates.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2192
									
								
								_module/nss/0i_associates.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										70
									
								
								_module/nss/0i_color.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								_module/nss/0i_color.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0i_color | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Include scripts that are used to change the color of names and text. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Basic color codes.                                             Message Notes | ||||
| const string AI_COLOR_BLACK = "000";       // <c   > <c\x20\x20\x20> Nothing. | ||||
| const string AI_COLOR_WHITE = "999";       // <c<><63><EFBFBD>> <c\xFF\xFF\xFF> _Debug messages. | ||||
| const string AI_COLOR_GRAY = "666";        // <c<><63><EFBFBD>> <c\xAA\xAA\xAA> Server messages | ||||
| const string AI_COLOR_YELLOW = "990";      // <c<><63> > <c\xFF\xFF\x20> Generic messages to players. | ||||
| const string AI_COLOR_DARK_YELLOW = "660"; // <c  <20>> <c\xAA\xAA\x20> | ||||
| const string AI_COLOR_RED = "900";         // <c<>  > <c\xFF\x20\x20> Negative message to players. | ||||
| const string AI_COLOR_DARK_RED = "600";    // <c  <20>> <c\xAA\x20\x20> | ||||
| const string AI_COLOR_GREEN = "080";       // <c <20> > <c\x20\xFF\x20> Positive message to players. | ||||
| const string AI_COLOR_DARK_GREEN = "060";  // <c <20> > <c\x20\xAA\x20> | ||||
| const string AI_COLOR_BLUE = "009";        // <c  <20>> <c\x20\x20\xFF> | ||||
| const string AI_COLOR_DARK_BLUE = "006";   // <c  <20>> <c\x20\x20\xAA> In game descriptive text. | ||||
| const string AI_COLOR_CYAN = "099";        // <c <20><>> <c\x20\xFF\xFF> | ||||
| const string AI_COLOR_DARK_CYAN = "066";   // <c <20><>> <c\x20\xAA\xAA> | ||||
| const string AI_COLOR_MAGENTA = "909";     // <c<> <20>> <c\xFF\x20\xFF> | ||||
| const string AI_COLOR_DARK_MAGENTA = "606";// <c<> <20>> <c\xAA\x20\xAA> | ||||
| const string AI_COLOR_LIGHT_MAGENTA = "868"; // <<3C>c<EFBFBD>> <c\xAA\xE2\xAA> Combat text: Enemy name color. | ||||
| const string AI_COLOR_ORANGE = "950";      // <c<><63> > <c\xFF\x8E\x20> | ||||
| const string AI_COLOR_DARK_ORANGE = "940"; // <c<>q > <c\xFF\x71\x20>  Combat text: base text color. | ||||
| const string AI_COLOR_GOLD = "860";        // <c<><63> > <c\xE2\xAA\x20> | ||||
| // Strips the color codes from sText | ||||
| string ai_StripColorCodes(string sText); | ||||
| // This function will make sString be the specified color | ||||
| // as specified in sRGB.  RGB is the Red, Green, and Blue | ||||
| // Each color can have a value from 0 to 9. | ||||
| //   1 - 0(20)[ ] 142 - 5(8E)[?] | ||||
| //  32 - 1(20)[ ] 170 - 6(AA)[<5B>] | ||||
| //  57 - 2(39)[9] 198 - 7(C6)[<5B>] | ||||
| //  85 - 3(55)[U] 226 - 8(E2)[<5B>] | ||||
| // 113 - 4(71)[q] 255 - 9(FE)[<5B>] | ||||
| string  ai_AddColorToText(string sText, string sRGB = AI_COLOR_WHITE); | ||||
|  | ||||
| string ai_StripColorCodes(string sText) | ||||
| { | ||||
|     string sColorCode, sChar; | ||||
|     int nStringLength = GetStringLength(sText); | ||||
|     int i = FindSubString(sText, "<c", 0); | ||||
|     while(i != -1) | ||||
|     { | ||||
|         sText = GetStringLeft(sText, i) + GetStringRight(sText, nStringLength -(i + 6)); | ||||
|         nStringLength = GetStringLength(sText); | ||||
|         i = FindSubString(sText, "<c", i); | ||||
|     } | ||||
|     i = FindSubString(sText, "</", 0); | ||||
|     while(i != -1) | ||||
|     { | ||||
|         sText = GetStringLeft(sText, i) + GetStringRight(sText, nStringLength -(i + 4)); | ||||
|         nStringLength = GetStringLength(sText); | ||||
|         i = FindSubString(sText, "</", i); | ||||
|     } | ||||
|     return sText; | ||||
| } | ||||
| string  ai_AddColorToText(string sText, string sRGB = AI_COLOR_WHITE) | ||||
| { | ||||
|     // Old info The magic characters(padded -- the last three characters are the same). | ||||
|     string sColorCodes = "\x20\x20\x39\x55\x71\x8E\xAA\xC6\xE2\xFF"; | ||||
|     if(FindSubString(sText, "<c", 0) != -1) sText = ai_StripColorCodes(sText); | ||||
|     return "<c" + // Begin the color token. | ||||
|            GetSubString(sColorCodes, StringToInt(GetSubString(sRGB, 0, 1)), 1) + // red | ||||
|            GetSubString(sColorCodes, StringToInt(GetSubString(sRGB, 1, 1)), 1) + // green | ||||
|            GetSubString(sColorCodes, StringToInt(GetSubString(sRGB, 2, 1)), 1) + // blue | ||||
|            ">"  + // End the color token | ||||
|             sText + "</c>"; | ||||
| } | ||||
							
								
								
									
										3498
									
								
								_module/nss/0i_combat.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3498
									
								
								_module/nss/0i_combat.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										667
									
								
								_module/nss/0i_constants.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										667
									
								
								_module/nss/0i_constants.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,667 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| // Name: 0i_constants | ||||
| // Programmer: Philos | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Include script for handling all constants for the ai. | ||||
|  These constants are static and can only be changed in the toolset. | ||||
|  Changes to any constants will not take effect until the scripts are recompiled. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| const string PHILOS_VERSION = "Philos' Enhancing Player System (PEPS) version:07.20.25"; | ||||
| // The following constants are designed to be changed to allow the AI to work | ||||
| // differently based on what a developer wants. | ||||
| // If you change these constants make sure the database has been removed | ||||
| // so the ai_SetAIRules() will rewrite the new server rule values. | ||||
| // File Name: peps_database.sqlite3 | ||||
| //**********************************  SERVER *********************************** | ||||
| // Turn On/Off Debug. You can only use the debug with the pi_debug/pe_debug scripts. | ||||
| // This will only work if you are using the PEPS menu system. | ||||
| const int AI_DEBUG = FALSE; | ||||
| // Defines if we are compiling for single player or a server. Always on for servers! | ||||
| const int AI_SERVER = FALSE; | ||||
| // The number of classes allowed for a creature to take in the server/module. | ||||
| const int AI_MAX_CLASSES_PER_CHARACTER = 8; | ||||
| // Taunts cool down time before the AI attemps another Taunt. | ||||
| const int AI_TAUNT_COOLDOWN = 3; | ||||
| // Animal Empathy cool down time before the AI attemps another check. | ||||
| const int AI_EMPATHY_COOLDOWN = 3; | ||||
| // Arcane Spell failure% or less than, for a caster to still try to cast a spell. | ||||
| const int AI_ASF_WILL_USE = 15; | ||||
| // Monsters chance to heal while in combat per round. | ||||
| const int AI_MONSTER_HEAL_IN_COMBAT_CHANCE = 70; | ||||
| // Monsters chance to heal when out of combat per heart beat. | ||||
| const int AI_MONSTER_HEAL_OUT_COMBAT_CHANCE = 70; | ||||
| // Allows Henchman to have a widget if using the henchman AI. | ||||
| const int AI_HENCHMAN_WIDGET = TRUE; | ||||
| // Change the Custom token number if it conflicts with your server. | ||||
| const int AI_BASE_CUSTOM_TOKEN = 1000; | ||||
| // Delay between creatures casting Buff spells. Must be minimum of 0.1 seconds. | ||||
| const float AI_HENCHMAN_BUFF_DELAY = 0.2; | ||||
|  | ||||
| //*******************  These can be changed within the game  ******************* | ||||
| // Moral checks on or off. If wounded they will make Will saves, if they fail the flee. | ||||
| const int AI_MORAL_CHECKS = FALSE; | ||||
| // Allows monsters to prebuff before combat starts. | ||||
| const int AI_PREBUFF = TRUE; | ||||
| // Allows monsters cast summons spells when prebuffing. | ||||
| const int AI_PRESUMMONS = TRUE; | ||||
| // Allows monsters to use tactical AI scripts such as ambush, flanker, ranged. | ||||
| const int AI_TACTICAL = TRUE; | ||||
| // Enemies may summon familiars and Animal companions and will be randomized. | ||||
| const int AI_SUMMON_COMPANIONS = FALSE; | ||||
| // Allow the AI to move during combat base on the situation and action taking. | ||||
| const int AI_ADVANCED_MOVEMENT = TRUE; | ||||
| // Follow Item Level Restrictions for AI. | ||||
| const int AI_ITEM_LEVEL_RESTRICTIONS = FALSE; | ||||
| // Allow the AI to use Use Magic Device. | ||||
| const int AI_USE_MAGIC_DEVICE = TRUE; | ||||
| // Allow the AI to use healing kits. | ||||
| const int AI_HEALING_KITS = TRUE; | ||||
| // Associates are permanent and don't get removed when the master dies. | ||||
| const int AI_COMPANIONS_PERMANENT = FALSE; | ||||
| // Monster AI's chance (0 to 100) to attack the weakest target instead of the nearest. | ||||
| // The higher the number the harder the encounter with monsters! | ||||
| const int AI_TARGET_WEAKEST = 0; | ||||
| // Variable that can change the distance creatures will come and attack after | ||||
| // hearing a shout from an ally that sees or hears an enemy. | ||||
| // Or when searching for an invisible, heard enemy. | ||||
| // 10.0 Short, 30.0 Average, 40.0 Long, 60.0 Huge. | ||||
| const float AI_SEARCH_DISTANCE = 30.0; | ||||
| // Enemy corpses remain on the floor instead of dissappearing. | ||||
| const int AI_CORPSE_REMAIN = FALSE; | ||||
| // Monsters will wander around when not in combat. | ||||
| const int AI_WANDER = FALSE; | ||||
| // Variable distance monsters can wander away from their spawn point. | ||||
| const float AI_WANDER_DISTANCE = 0.0; | ||||
| // Variable that allows monsters to open doors when wandering around out of combat. | ||||
| const int AI_OPEN_DOORS = FALSE; | ||||
| // Monster's actual perception distance. | ||||
| // 8 Short(10 sight/listen) 9 Medium(20 sight/listen) 10 Long(35 sight/20 listen) | ||||
| // 11 Default(Based on appearance.2da Most creatures use 9, bosses use 10). | ||||
| const int AI_MONSTER_PERCEPTION = 11; | ||||
| // Should the AI auto adjust the XP scale to remove party size penalty? | ||||
| const int AI_PARTY_SCALE = FALSE; | ||||
|  | ||||
| //****************************  DM Based Constants  **************************** | ||||
| // The constant the server wants set to allow players to use specific widgets buttons. | ||||
| // 0 Allows all buttons. See ASSOCIATE_WIDGET_BUTTONS below for values needed to be | ||||
| // added to block those buttons. | ||||
| // Example: BTN_CMD_GHOST_MODE = 0x00000800; To remove you would put 2048 below. | ||||
| // Since Hex 800 is Decimal 2048. | ||||
| const int AI_DM_WIDGET_ACCESS_BUTTONS = 0; | ||||
| // The constant the server wants set to allow players to use specific AI buttons. | ||||
| // 0 Allows all buttons. See ASSOCIATE_AI_BUTTONS below for values needed to be | ||||
| // added to block those buttons. | ||||
| // Example: BTN_AI_MAGIC_LEVEL = 0x00000040; To remove you would put 64 below. | ||||
| // Since Hex 40 is Decimal 64. Adding BTN_AI_LOOT = 0x00001000; to that would be | ||||
| // 64 + 4096 = 4160 to Block Magic Level and Auto Looting. | ||||
| const int AI_DM_AI_ACCESS_BUTTONS = 0; | ||||
| //**************************  CONVERSATION CONSTANTS  ************************** | ||||
| // Player's can tell their associates to ignore enemy associates. | ||||
| const int AI_IGNORE_ASSOCIATES_ON = TRUE; | ||||
| // Associates with a Taunt skill higher than their level can be told to taunt. | ||||
| const int AI_TAUNTING_ON = TRUE; | ||||
| // Associates that cast spells can be told to use counterspell. | ||||
| const int AI_COUNTERSPELLING_ON = TRUE; | ||||
| // Associates with lore skill higher than the master can identify items. | ||||
| const int AI_IDENTIFY_ON = TRUE; | ||||
| // Associates can be called upon to scout ahead for monsters. | ||||
| const int AI_SCOUT_AHEAD_ON = TRUE; | ||||
| // A player can open a henchmen's inventory. | ||||
| const int AI_OPEN_INVENTORY = TRUE; | ||||
| // Allows players to have associates pickup loot. | ||||
| const int AI_PICKUP_LOOT = TRUE; | ||||
| // Allows players to remove a henchman. | ||||
| const int AI_REMOVE_HENCHMAN_ON = FALSE; | ||||
| //*****************************  Health Constants  ***************************** | ||||
| // % of health for when a creature is considered wounded. | ||||
| const int AI_HEALTH_WOUNDED = 50; | ||||
| // % of health when creature is considered badly wounded. | ||||
| const int AI_HEALTH_BLOODY = 25; | ||||
| //*****************************  MORAL CONSTANTS  ****************************** | ||||
| // Moral checks are only made once a creature is below AI_HEALTH_WOUNDED. | ||||
| // The moral DC is AI_MORAL_DC - the number of Allies. Default: 5 | ||||
| const int AI_WOUNDED_MORAL_DC = 5; | ||||
| // Once a creature goes below AI_HEALTHY_BLOODY then it uses this moral DC. Default: 15 | ||||
| const int AI_BLOODY_MORAL_DC = 15; | ||||
| //******************************* WINDOW CONSTANTS ***************************** | ||||
| const string AI_MAIN_NUI = "ai_main_nui"; | ||||
| const string AI_COMMAND_NUI = "_command_nui"; | ||||
| const string AI_NUI = "_ai_nui"; | ||||
| const string AI_WIDGET_NUI = "_widget_nui"; | ||||
| const string AI_LOOTFILTER_NUI = "_lootfilter_nui"; | ||||
| const string AI_COPY_NUI = "_copy_nui"; | ||||
| const string AI_PLUGIN_NUI = "ai_plugin_nui"; | ||||
| const string AI_QUICK_WIDGET_NUI = "_quick_widget_nui"; | ||||
| const string AI_SPELL_MEMORIZE_NUI = "_spell_memorize_nui"; | ||||
| const string AI_SPELL_KNOWN_NUI = "_spell_known_nui"; | ||||
| const string AI_SPELL_DESCRIPTION_NUI = "ai_spell_desc_nui"; | ||||
| const string AI_EFFECT_ICON_NUI = "ai_effect_icon_nui"; | ||||
| //******************************* CORE CONSTANTS ******************************* | ||||
| // The following constants are core constants and changing any of these without | ||||
| // understanding the whole system could cause unforseen results. | ||||
| //                            CHANGE AT YOUR OWN RISK. | ||||
| // Variable used to asave a monster object for changing. | ||||
| const string AI_MONSTER_OBJECT = "AI_MONSTER_OBJECT"; | ||||
| // Variable used to save a monsters json for changing. | ||||
| const string AI_MONSTER_JSON = "AI_MONSTER_JSON"; | ||||
| // Variable used to let PEPS know that a monster plugin changed the monster. | ||||
| const string AI_MONSTER_CHANGED = "AI_MONSTER_CHANGED"; | ||||
| // Variable used to save an associates class list to change known list json. | ||||
| const string AI_CLASS_LIST_JSON = "AI_CLASS_LIST_JSON"; | ||||
| // Startup variable to tell plugins that we have started. | ||||
| const string AI_STARTING_UP = "AI_STARTING_UP"; | ||||
| // Add plugin variable to tell plugins that we are adding them to PEPS. | ||||
| const string AI_ADD_PLUGIN = "AI_ADD_PLUGIN"; | ||||
| // Startup variable to tell plugins what json array to add their plugin to. | ||||
| const string AI_JSON_PLUGINS = "AI_JSON_PLUGINS"; | ||||
| // Plugin variable to have plugins return if they setup the plugin in the json for PEPS. | ||||
| const string AI_PLUGIN_SET = "AI_PLUGIN_SET"; | ||||
| // Monster modification variable to let PEPS know what mods are available. | ||||
| const string AI_MONSTER_MOD_JSON = "AI_MONSTER_MOD_JSON"; | ||||
| // The maximum number of henchman the code works with. | ||||
| const int AI_MAX_HENCHMAN = 12; | ||||
| // Delay between Henchman casting Healing spells. Must be minimum of 0.5 seconds. | ||||
| const float AI_HENCHMAN_HEALING_DELAY = 6.0; | ||||
| // A variable that can be set on creatures to stop mobile animations. | ||||
| const string AI_NO_ANIMATION = "AI_NO_ANIMATION"; | ||||
| // How many seconds in a combat round. | ||||
| const int AI_COMBAT_ROUND_IN_SECONDS = 6; | ||||
| // Used for actions that take x seconds but don't have an action constant. | ||||
| const string AI_COMBAT_WAIT_IN_SECONDS = "AI_COMBAT_WAIT_IN_SECONDS"; | ||||
| // Constants used to define the difficulty of the battle for associates. | ||||
| //    20+    : Impossible     - Cannot win. | ||||
| // 17 to  19 : Overpowering   - Use all of our powers. | ||||
| // 15 to  16 : Very Difficult - Use all of our power (Highest level spells). | ||||
| // 11 to  14 : Challenging    - Use most of our power (Higher level powers). | ||||
| //  8 to  10 : Moderate       - Use half of our power (Mid level powers and less). | ||||
| //  5 to   7 : Easy           - Use our weaker powers (Lowest level powers). | ||||
| //  2 to   4 : Effortless     - Don't waste spells and powers on this. | ||||
| //  1 or less: Pointless      - We probably should ignore these dangers. | ||||
| const int AI_COMBAT_IMPOSSIBLE = 21; | ||||
| const int AI_COMBAT_OVERPOWERING = 17; | ||||
| const int AI_COMBAT_VERY_DIFFICULT = 15; | ||||
| const int AI_COMBAT_CHALLENGING = 11; | ||||
| const int AI_COMBAT_MODERATE = 10; | ||||
| const int AI_COMBAT_EASY = 7; | ||||
| const int AI_COMBAT_EFFORTLESS = 4; | ||||
| // Variables used to keep track of enemies in combat. | ||||
| const string AI_ENEMY = "AI_ENEMY"; // The enemy objects. | ||||
| const string AI_ENEMY_DISABLED = "AI_ENEMY_DISABLED"; // Int if they are disabled. | ||||
| const string AI_ENEMY_PERCEIVED = "AI_ENEMY_PERCEIVED"; // TRUE if we have seen or heard them, FALSE if not. | ||||
| const string AI_ENEMY_RANGE = "AI_ENEMY_RANGE"; // The range from OBJECT_SELF. | ||||
| const string AI_ENEMY_COMBAT = "AI_ENEMY_COMBAT"; // Combat rating: (BAB + AC - 10) / 2 | ||||
| const string AI_ENEMY_MELEE = "AI_ENEMY_MELEE"; // Enemies within 5 meters - Allies within 5 meters. | ||||
| const string AI_ENEMY_HEALTH = "AI_ENEMY_HEALTH"; // % of hitpoints. | ||||
| const string AI_ENEMY_NUMBERS = "AI_ENEMY_NUM"; // Number of enemies in combat. | ||||
| const string AI_ENEMY_POWER = "AI_ENEMY_POWER"; // (Level * Health %) / 100 added for each enemy to this. | ||||
| const string AI_ENEMY_NEAREST = "AI_ENEMY_NEAREST"; // Nearest enemy to OBJECT_SELF. | ||||
| // Variables used to keep track of allies in combat. | ||||
| const string AI_ALLY = "AI_ALLY"; // All friendly creatures | ||||
| const string AI_ALLY_DISABLED = "AI_ALLY_DISABLED"; // Int if they are disabled. | ||||
| const string AI_ALLY_PERCEIVED = "AI_ALLY_PERCEIVED"; // All allies are set to be seen and heard. | ||||
| const string AI_ALLY_RANGE = "AI_ALLY_RANGE"; // The range from OBJECT_SELF. | ||||
| const string AI_ALLY_COMBAT = "AI_ALLY_COMBAT"; // Combat rating: (BAB + AC - 10) / 2 | ||||
| const string AI_ALLY_MELEE = "AI_ALLY_MELEE"; // Enemies within 5 meters - Allies within 5 meters. | ||||
| const string AI_ALLY_HEALTH = "AI_ALLY_HEALTH"; // % of hitpoints. | ||||
| const string AI_ALLY_NUMBERS = "AI_ALLY_NUM"; // Number of allies in combat. | ||||
| const string AI_ALLY_POWER = "AI_ALLY_POWER"; // (Level * Health %) / 100 added for each enemy to this. | ||||
| // Variable name used to define the ai scripts being used by creatures. | ||||
| const string AI_DEFAULT_SCRIPT = "AI_DEFAULT_SCRIPT"; | ||||
| const string AI_COMBAT_SCRIPT = "AI_COMBAT_SCRIPT"; | ||||
| // Constants used in a creatures listening patterns. | ||||
| const string AI_I_SEE_AN_ENEMY = "AI_I_SEE_AN_ENEMY"; | ||||
| const string AI_I_HEARD_AN_ENEMY = "AI_I_HEARD_AN_ENEMY"; | ||||
| const string AI_ATKED_BY_WEAPON = "AI_ATK_BY_WEAPON"; | ||||
| const string AI_ATKED_BY_SPELL = "AI_ATK_BY_SPELL"; | ||||
| const string AI_I_AM_WOUNDED = "AI_I_AM_WOUNDED"; | ||||
| const string AI_I_AM_DEAD = "AI_I_AM_DEAD"; | ||||
| const string AI_I_AM_DISEASED = "AI_I_AM_DISEASED"; | ||||
| const string AI_I_AM_POISONED = "AI_I_AM_POISONED"; | ||||
| const string AI_I_AM_WEAK = "AI_I_AM_WEAK"; | ||||
| const int AI_ALLY_SEES_AN_ENEMY = 1; | ||||
| const int AI_ALLY_HEARD_AN_ENEMY = 2; | ||||
| const int AI_ALLY_ATKED_BY_WEAPON = 3; | ||||
| const int AI_ALLY_ATKED_BY_SPELL = 4; | ||||
| const int AI_ALLY_IS_WOUNDED = 5; | ||||
| const int AI_ALLY_IS_DEAD = 6; | ||||
| const int AI_ALLY_IS_DISEASED = 7; | ||||
| const int AI_ALLY_IS_POISONED = 8; | ||||
| const int AI_ALLY_IS_WEAK = 9; | ||||
| const string AI_MY_TARGET = "AI_MY_TARGET"; | ||||
| // Constant used by monsters to reduce checks while searching for unseen targets. | ||||
| const string AI_AM_I_SEARCHING = "AI_AM_I_SEARCHING"; | ||||
| // Used to keep track of oCreature attempting to hide. | ||||
| const string AI_TRIED_TO_HIDE = "AI_TRIED_TO_HIDE"; | ||||
| // Constant used by creatures to keep track of invisible creatures. | ||||
| const string AI_IS_INVISIBLE = "AI_IS_INVISIBLE"; | ||||
| // Constants used in combat to keep track of a creatures last action. | ||||
| // 0+ is the last spell cast from the line number in Spells.2da. | ||||
| const string sLastActionVarname = "AI_LAST_ACTION"; | ||||
| const int AI_LAST_ACTION_CAST_SPELL = -1; | ||||
| const int AI_LAST_ACTION_NONE = -2; | ||||
| const int AI_LAST_ACTION_MELEE_ATK = -3; | ||||
| const int AI_LAST_ACTION_RANGED_ATK = -4; | ||||
| const int AI_LAST_ACTION_USED_FEAT = -5; | ||||
| const int AI_LAST_ACTION_USED_ITEM = -6; | ||||
| const int AI_LAST_ACTION_USED_SKILL = -7; | ||||
| const int AI_LAST_ACTION_MOVE = -8; | ||||
| // Variable name used to keep track of Action Modes. | ||||
| const string AI_CURRENT_ACTION_MODE = "AI_CURRENT_ACTION_MODE"; | ||||
| // Variable name used to keep track of object usage by the AI. | ||||
| const string AI_OBJECT_IN_USE = "AI_OBJECT_IN_USE"; | ||||
| // Variable name used to keep a creatures attacked targets. | ||||
| const string AI_ATTACKED_PHYSICAL = "AI_ATTACKED_PHYSICAL"; | ||||
| const string AI_ATTACKED_SPELL = "AI_ATTACKED_SPELL"; | ||||
| // Variable name used to keep track of a creatures normal polymorph form. | ||||
| const string AI_NORMAL_FORM = "AI_NORMAL_FORM"; | ||||
| // Variable name used to keep track if a creature has been buffed yet. | ||||
| const string AI_CASTER_BUFFS_SET = "AI_CASTER_BUFFS_SET"; | ||||
| // Variable name used to keep track of rounds in combat for a custom ai script. | ||||
| const string AI_ROUND = "AI_ROUND"; | ||||
| // Combat Ranges | ||||
| const float AI_RANGE_MELEE = 5.0f; // Anyone within this is considered to be in melee. | ||||
| const float AI_RANGE_CLOSE = 8.0f; // For anything requiring to be within 30'. | ||||
| const float AI_RANGE_LONG = 15.0f; // Mainly used for distance ranged attacks. | ||||
| const float AI_RANGE_PERCEPTION = 35.0f; // This is the distance for perception in battle. | ||||
| const float AI_RANGE_BATTLEFIELD = 40.0f; // This is the size of the battlefield area. | ||||
| // Spell ranges. | ||||
| const float AI_SHORT_DISTANCE = 8.0f; | ||||
| const float AI_MEDIUM_DISTANCE = 20.0f; | ||||
| const float AI_LONG_DISTANCE = 40.0f; | ||||
| // When computer checks if a creature should cast a specific spell at a target. | ||||
| // Computer makes a spell check vs the targets saving throw. | ||||
| // Spell check roll for the caster is | ||||
| // [Innate spell Level + Random (AI_SPELL_CHECK_DIE) + AI_SPELL_CHECK_BONUS] | ||||
| // If the spell gives a save for half (i.e. FireBall) and the target does not have | ||||
| // Evasion then they get an additional bonus of AI_SPELL_CHECK_NO_EVASION_BONUS. | ||||
| const int AI_SPELL_CHECK_DIE = 6; | ||||
| const int AI_SPELL_CHECK_BONUS = 3; | ||||
| const int AI_SPELL_CHECK_NO_EVASION_BONUS = 10; | ||||
| // When the computer checks if a creature should use defensive casting it looks | ||||
| // at the spell level + AI_DEFENSIVE_CASTING_DC vs casters concentration | ||||
| // and feat bonuses (i.e. COMBAT_CASTING) + Random (AI_DEFENSIVE_CASTING_ROLL). | ||||
| const int AI_DEFENSIVE_CASTING_DC = 19; // 19 will allow them to use it at 50% effectiveness. | ||||
| const int AI_DEFENSIVE_CASTING_DIE = 10; | ||||
| // When the computer checks to see if it should cast in melee combat it looks | ||||
| // at CASTING_IN_MELEE_DC + SpellLevel + (Num of creatures in melee * GetHitDice (NearestEnemy)); | ||||
| // vs the casters concentration + Random (AI_CASTING_IN_MELEE_ROLL). | ||||
| const int AI_CASTING_IN_MELEE_DC = 10; | ||||
| const int AI_CASTING_IN_MELEE_ROLL = 10; | ||||
| // For getting a specific class the following constants were added to flesh out | ||||
| // the CLASS_TYPE_* | ||||
| const int AI_CLASS_TYPE_CASTER = -1; | ||||
| const int AI_CLASS_TYPE_DIVINE = -2; | ||||
| const int AI_CLASS_TYPE_ARCANE = -3; | ||||
| const int AI_CLASS_TYPE_WARRIOR = -4; | ||||
| // For getting a specific race the following constants were added to flesh out | ||||
| // the RACIAL_TYPE_* | ||||
| const int AI_RACIAL_TYPE_ANIMAL_BEAST = -1; | ||||
| const int AI_RACIAL_TYPE_HUMANOID = -2; | ||||
| // Bitwise constants for negative conditions we might want to try to cure | ||||
| const int AI_CONDITION_POISON         = 0x00000001; | ||||
| const int AI_CONDITION_DISEASE        = 0x00000002; | ||||
| const int AI_CONDITION_BLINDDEAF      = 0x00000004; | ||||
| const int AI_CONDITION_ATK_DECREASE   = 0x00000008; | ||||
| const int AI_CONDITION_DMG_DECREASE   = 0x00000010; | ||||
| const int AI_CONDITION_DMG_I_DECREASE = 0x00000020; | ||||
| const int AI_CONDITION_SKILL_DECREASE = 0x00000040; | ||||
| const int AI_CONDITION_SAVE_DECREASE  = 0x00000080; | ||||
| const int AI_CONDITION_SR_DECREASE    = 0x00000100; | ||||
| const int AI_CONDITION_AC_DECREASE    = 0x00000200; | ||||
| const int AI_CONDITION_SLOW           = 0x00000400; | ||||
| const int AI_CONDITION_ABILITY_DRAIN  = 0x00000800; | ||||
| const int AI_CONDITION_LEVEL_DRAIN    = 0x00001000; | ||||
| const int AI_CONDITION_CHARMED        = 0x00002000; | ||||
| const int AI_CONDITION_DAZED          = 0x00004000; | ||||
| const int AI_CONDITION_STUNNED        = 0x00008000; | ||||
| const int AI_CONDITION_FRIGHTENED     = 0x00010000; | ||||
| const int AI_CONDITION_CONFUSED       = 0x00020000; | ||||
| const int AI_CONDITION_CURSE          = 0x00040000; | ||||
| const int AI_CONDITION_PARALYZE       = 0x00080000; | ||||
| const int AI_CONDITION_DOMINATED      = 0x00100000; | ||||
| // Database constants for Associate modes. | ||||
| const string AI_MODE_DB_TABLE = "AI_MODE_DB_TABLE"; | ||||
| // Bitwise constants for Associate modes that are used with Get/SetAssociateMode(). | ||||
| const string sAIModeVarname = "ASSOCIATE_MODES"; | ||||
| //const int AI_MODE_DISTANCE_CLOSE =    0x00000001; // Stays within AI_DISTANCE_CLOSE of master. | ||||
| //const int AI_MODE_DISTANCE_MEDIUM =   0x00000002; // Stays within AI_DISTANCE_MEDIUM of master. | ||||
| const int AI_MODE_ACTION_GHOST =        0x00000004; // Defines if the player is using Ghost mode when using associate actions. | ||||
| const int AI_MODE_SELF_HEALING_OFF =    0x00000008; // Creature will not use healing items or spells on self. | ||||
| const int AI_MODE_PARTY_HEALING_OFF =   0x00000010; // Creature will not use healing items or spells on party. | ||||
| const int AI_MODE_GHOST =               0x00000020; // Creature can move through other creatures. | ||||
| const int AI_MODE_OPEN_DOORS =          0x00000040; // Creature will attempted to open all doors. | ||||
| const int AI_MODE_EQUIP_WEAPON_OFF =    0x00000080; // The AI will not equip weapons. | ||||
| const int AI_MODE_BASH_LOCKS =          0x00000100; // Will bash locks if cannot open door/placeable. | ||||
| const int AI_MODE_AGGRESSIVE_SEARCH =   0x00000200; // Sets associate to continuous search mode. | ||||
| const int AI_MODE_AGGRESSIVE_STEALTH =  0x00000400; // Sets associate to continuous stealth mode. | ||||
| const int AI_MODE_PICK_LOCKS =          0x00000800; // Will pick locks if possible. | ||||
| const int AI_MODE_DISARM_TRAPS =        0x00001000; // Will disarm traps. | ||||
| const int AI_MODE_SCOUT_AHEAD =         0x00002000; // Will move ahead of master and scout. | ||||
| const int AI_MODE_DEFEND_MASTER =       0x00004000; // Will attack enemies attacking our master. | ||||
| const int AI_MODE_STAND_GROUND =        0x00008000; // Will stay in one place until new command. | ||||
| const int AI_MODE_STOP_RANGED =         0x00010000; // Will not use ranged weapons. | ||||
| const int AI_MODE_FOLLOW =              0x00020000; // Keeps associate following master ignoring combat. | ||||
| const int AI_MODE_PICKUP_ITEMS =        0x00040000; // Will pickup up all items for master. | ||||
| const int AI_MODE_COMMANDED =           0x00080000; // In Command mode then don't follow, search, etc. | ||||
| const int AI_MODE_IGNORE_TRAPS =        0x00100000; // Creature will ignore traps on the floor. | ||||
| const int AI_MODE_NO_STEALTH =          0x00200000; // Will not cast invisibilty or use stealth. | ||||
| const int AI_MODE_DO_NOT_SPEAK =        0x00400000; // Tells the henchmen to be silent and not talk. | ||||
| const int AI_MODE_CHECK_ATTACK =        0x00800000; // Will only engage in combats they think they can win. | ||||
| const int AI_MODE_IGNORE_ASSOCIATES =   0x01000000; // Will ignore associates in combat. | ||||
| //const int AI_MODE_ =                  0x02000000; // Not used. | ||||
| //const int AI_MODE_ =                  0x04000000; // Not used. | ||||
| //const int AI_MODE_ =                  0x08000000; // Not used. | ||||
| //const int AI_MODE_ =                  0x10000000; // Not used. | ||||
| //const int AI_MODE_ =                  0x20000000; // Not used. | ||||
| //const int AI_MODE_ =                  0x40000000; // Not used. | ||||
| //const int AI_MODE_ =                  0x80000000; // Not used. | ||||
| // Bitwise constants for Associate magic modes that are used with Get/SetAssociateMagicMode(). | ||||
| const string sMagicModeVarname = "ASSOCIATE_MAGIC_MODES"; | ||||
| const int AI_MAGIC_BUFF_MASTER =         0x00000001; // Buffs master before other allies. | ||||
| const int AI_MAGIC_NO_MAGIC =            0x00000002; // Will not use any magic (Spells, abilities). | ||||
| const int AI_MAGIC_DEFENSIVE_CASTING =   0x00000004; // Will only cast defensive spells. | ||||
| const int AI_MAGIC_OFFENSIVE_CASTING =   0x00000008; // Will only cast offensive spells. | ||||
| const int AI_MAGIC_STOP_DISPEL =         0x00000010; // Will not cast dispel type spells. | ||||
| const int AI_MAGIC_BUFF_AFTER_REST =     0x00000020; // Will buff the party after resting. | ||||
| const int AI_MAGIC_NO_MAGIC_ITEMS =      0x00000040; // Will not use magic items in combat. | ||||
| const int AI_MAGIC_CURE_SPELLS_OFF =     0x00000080; // Will not cast cure spells. | ||||
| const int AI_MAGIC_EFFECT_ICON_REPORT =  0x00000100; // Sets each player to report Effect Icons to chat. | ||||
| //const int  =                           0x00000200; // Not used. | ||||
| //const int  =                           0x00000400; // Not used. | ||||
| const int AI_MAGIC_NO_SPONTANEOUS_CURE = 0x00000800; // Caster will stop using spontaneous cure spells. | ||||
| //const int AI_MAGIC_ =                  0x00001000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00002000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00004000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00008000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00010000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00020000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00040000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00080000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00100000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00200000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00400000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x00800000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x01000000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x02000000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x04000000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x08000000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x10000000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x20000000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x40000000; // Not used. | ||||
| //const int AI_MAGIC_ =                  0x80000000; // Not used. | ||||
| // Use by NUI windows to stop saving move states while loading. | ||||
| const string AI_NO_NUI_SAVE = "AI_NO_NUI_SAVE"; | ||||
| // Bitwise menu constants for Widget buttons that are used with Get/SetAssociateWidgetButtons(). | ||||
| const string sWidgetButtonsVarname = "ASSOCIATE_WIDGET_BUTTONS"; | ||||
| const int BTN_WIDGET_OFF       = 0x00000001; // Removes the widget from the screen, For PC it removes all associates. | ||||
| const int BTN_WIDGET_LOCK      = 0x00000002; // Locks the widget to the current coordinates. | ||||
| const int BTN_CMD_GUARD        = 0x00000004; // Command associates to Guard Me. PC widget only. | ||||
| const int BTN_CMD_FOLLOW       = 0x00000008; // Command associates to Follow. PC widget only. | ||||
| const int BTN_CMD_HOLD         = 0x00000010; // Command associates to Stand Ground. PC widget only. | ||||
| const int BTN_CMD_ATTACK       = 0x00000020; // Command associates to Attack Nearest. PC widget only. | ||||
| const int BTN_BUFF_REST        = 0x00000040; // Buffs with long duration spells after resting. Associate widget only. | ||||
| const int BTN_BUFF_SHORT       = 0x00000080; // Buffs with short duration spells. | ||||
| const int BTN_BUFF_LONG        = 0x00000100; // Buffs with long duration spells. | ||||
| const int BTN_BUFF_ALL         = 0x00000200; // Buffs with all spells. | ||||
| const int BTN_CMD_ACTION       = 0x00000400; // Command associate to do an action. | ||||
| const int BTN_CMD_GHOST_MODE   = 0x00000800; // Toggle's associates ghost mode. | ||||
| const int BTN_CMD_AI_SCRIPT    = 0x00001000; // Toggle's special tactics ai scripts. | ||||
| const int BTN_CMD_PLACE_TRAP   = 0x00002000; // A trapper may place traps. | ||||
| const int BTN_CMD_CAMERA       = 0x00004000; // Places camera view on associate. | ||||
| const int BTN_CMD_INVENTORY    = 0x00008000; // Opens inventory of associate. | ||||
| const int BTN_CMD_FAMILIAR     = 0x00010000; // Summons familiar. | ||||
| const int BTN_CMD_COMPANION    = 0x00020000; // Summons Companion. | ||||
| const int BTN_CMD_SEARCH       = 0x00040000; // Command all associates to use search mode. PC widget only. | ||||
| const int BTN_CMD_STEALTH      = 0x00080000; // Command all associates to use stealth mode. PC widget only. | ||||
| const int BTN_CMD_SCOUT        = 0x00100000; // Command associate to scout ahead of the part. | ||||
| const int BTN_CMD_SPELL_WIDGET = 0x00200000; // Allows adding or removing spells from Spell Widget. | ||||
| const int BTN_CMD_JUMP_TO      = 0x00400000; // Player can make associates jump to them. | ||||
| const int BTN_WIDGET_VERTICAL  = 0x80000000; // Widget will be displayed vertical. | ||||
| // Bitwise menu constants for Associate AI buttons that are used with Get/SetAssociateAIButtons(). | ||||
| const string sAIButtonsVarname = "ASSOCIATE_AI_BUTTONS"; | ||||
| const int BTN_AI_FOR_PC             = 0x00000001; // PC use AI. PC widget only. | ||||
| const int BTN_AI_USE_RANGED         = 0x00000002; // AI uses ranged attacks. | ||||
| const int BTN_AI_USE_SEARCH         = 0x00000004; // AI uses Search. | ||||
| const int BTN_AI_USE_STEALTH        = 0x00000008; // AI uses Stealth. | ||||
| const int BTN_AI_REMOVE_TRAPS       = 0x00000010; // AI seeks out and removes traps. | ||||
| const int BTN_AI_PICK_LOCKS         = 0x00000020; // AI will attempt to pick locks. | ||||
| const int BTN_AI_MAGIC_LEVEL        = 0x00000040; // Increase chance to use magic in battle. | ||||
| const int BTN_AI_NO_SPONTANEOUS     = 0x00000080; // Stops the use of spontaneous spells. | ||||
| const int BTN_AI_NO_MAGIC_USE       = 0x00000100; // Will not use magic in battle. | ||||
| const int BTN_AI_NO_MAGIC_ITEM_USE  = 0x00000200; // Will not use magic items in battle. | ||||
| const int BTN_AI_DEF_MAGIC_USE      = 0x00000400; // Will use Defensive spells only in battle. | ||||
| const int BTN_AI_OFF_MAGIC_USE      = 0x00000800; // Will use Offensive spells only in battle. | ||||
| const int BTN_AI_LOOT               = 0x00001000; // Auto picking up loot on/off. | ||||
| const int BTN_AI_FOLLOW_TARGET      = 0x00002000; // Selects a target to follow. | ||||
| const int BTN_AI_HEAL_OUT           = 0x00004000; // Increase minimum hp required before ai heals out of combat. | ||||
| const int BTN_AI_PERC_RANGE         = 0x00008000; // Adjust the perception range of the henchman. | ||||
| const int BTN_AI_HEAL_IN            = 0x00010000; // Increase minimum hp required before ai heals in combat. | ||||
| const int BTN_AI_OPEN_DOORS         = 0x00020000; // AI will open all closed doors. | ||||
| const int BTN_AI_STOP_SELF_HEALING  = 0x00040000; // Stops AI from using any healing on self. | ||||
| const int BTN_AI_STOP_PARTY_HEALING = 0x00080000; // Stops AI from using any healing on party. | ||||
| const int BTN_AI_IGNORE_ASSOCIATES  = 0x00100000; // AI will deprioritize enemy associates. | ||||
| const int BTN_AI_STOP_CURE_SPELLS   = 0x00200000; // AI uses cure spells. | ||||
| const int BTN_AI_STOP_WEAPON_EQUIP  = 0x00400000; // AI can equip different weapons. | ||||
| const int BTN_AI_IGNORE_TRAPS       = 0x00800000; // AI will ignore traps on the floor. | ||||
| //const int BTN_AI                    = 0x01000000; // Not used. | ||||
| //const int BTN_AI                    = 0x02000000; // Not used. | ||||
| const int BTN_AI_BASH_LOCKS         = 0x04000000; // AI will attempt to bash any locks they can't get past. | ||||
| const int BTN_AI_REDUCE_SPEECH      = 0x08000000; // Reduce the associates speaking. | ||||
| // Bitwise menu constants for DM access for players Widget buttons uses BTN_CMD and BTN_BUFF bitwise see above. | ||||
| const string sDMWidgetAccessVarname = "AI_RULES_WIDGET_BUTTONS_ACCESS"; | ||||
| // Bitwise menu constants for DM access for players AI buttons uses BTN_AI bitwise see above. | ||||
| const string sDMAIAccessVarname = "AI_RULES_AI_BUTTONS_ACCESS"; | ||||
| // Variable name for DM widget buttons. | ||||
| const string sDMWidgetButtonVarname = "DM_WIDGET_BUTTONS"; | ||||
| // DM Widget buttons states. | ||||
| const int BTN_DM_WIDGET_OFF     = 0x00000001; // Removes the widget from the screen, For PC it removes all associates. | ||||
| const int BTN_DM_WIDGET_LOCK    = 0x00000002; // Locks the widget to the current coordinates. | ||||
| const int BTN_DM_CMD_GROUP1     = 0x00000004; // Does all the group 1 commands. | ||||
| const int BTN_DM_CMD_GROUP2     = 0x00000008; // Does all the group 2 commands. | ||||
| const int BTN_DM_CMD_GROUP3     = 0x00000010; // Does all the group 3 commands. | ||||
| const int BTN_DM_CMD_GROUP4     = 0x00000020; // Does all the group 4 commands. | ||||
| const int BTN_DM_CMD_GROUP5     = 0x00000040; // Does all the group 5 commands. | ||||
| const int BTN_DM_CMD_GROUP6     = 0x00000080; // Does all the group 6 commands. | ||||
| const int BTN_DM_CMD_CAMERA     = 0x00000100; // Selects new object to hold the camera view. | ||||
| const int BTN_DM_CMD_INVENTORY  = 0x00000200; // Selects a creature to open the inventory of. | ||||
| const int BTN_DM_CMD_MEMORIZE   = 0x00000400; // Allows associate to change memorized spells. | ||||
| // Bitwise constants for Associate loot options that are used with Get/SetAssociateLootMode(). | ||||
| const string sLootFilterVarname = "ASSOCIATE_LOOT_MODES"; | ||||
| const int AI_LOOT_PLOT              = 0x00000001; | ||||
| const int AI_LOOT_WEAPONS           = 0x00000002; | ||||
| const int AI_LOOT_ARMOR             = 0x00000004; | ||||
| const int AI_LOOT_SHIELDS           = 0x00000008; | ||||
| const int AI_LOOT_HEADGEAR          = 0x00000010; | ||||
| const int AI_LOOT_BELTS             = 0x00000020; | ||||
| const int AI_LOOT_BOOTS             = 0x00000040; | ||||
| const int AI_LOOT_CLOAKS            = 0x00000080; | ||||
| const int AI_LOOT_GLOVES            = 0x00000100; | ||||
| const int AI_LOOT_JEWELRY           = 0x00000200; | ||||
| const int AI_LOOT_POTIONS           = 0x00000400; | ||||
| const int AI_LOOT_SCROLLS           = 0x00000800; | ||||
| const int AI_LOOT_WANDS_RODS_STAVES = 0x00001000; | ||||
| const int AI_LOOT_GEMS              = 0x00002000; | ||||
| const int AI_LOOT_MISC              = 0x00004000; | ||||
| const int AI_LOOT_ARROWS            = 0x00008000; | ||||
| const int AI_LOOT_BOLTS             = 0x00010000; | ||||
| const int AI_LOOT_BULLETS           = 0x00020000; | ||||
| const int AI_LOOT_GIVE_TO_PC        = 0x80000000; | ||||
| // Default value for all loot filters to be on. | ||||
| const int AI_LOOT_ALL_ON = 262143; | ||||
| // Variable to keep track of who is in ghost mode. | ||||
| const string sGhostModeVarname = "AI_GHOST_MODE_ON"; | ||||
| // Variables for gold piece value to pickup items. | ||||
| const string AI_MIN_GOLD_ = "AI_MIN_GOLD_"; | ||||
| // Variable used to limit the spamming of NUI buttons. | ||||
| const string AI_DELAY_NUI_USE = "AI_DELAY_NUI_USE"; | ||||
| // Variable for maximum weight to pickup from looting. | ||||
| const string AI_MAX_LOOT_WEIGHT = "AI_MAX_LOOT_WEIGHT"; | ||||
| // Variable to change the size of the widget buttons. | ||||
| const string AI_WIDGET_BUTTON_SIZE = "AI_WIDGET_BUTTON_SIZE"; | ||||
| // Variable to change the difficulty so a player can adjust spell usage. | ||||
| const string AI_DIFFICULTY_ADJUSTMENT = "AI_DIFFICULTY_ADJUSTMENT"; | ||||
| // Variable to change the Healing % limit for out of combat. | ||||
| const string AI_HEAL_OUT_OF_COMBAT_LIMIT = "AI_HEAL_OUT_OF_COMBAT_LIMIT"; | ||||
| // Variable to change the Healing % limit for in combat. | ||||
| const string AI_HEAL_IN_COMBAT_LIMIT = "AI_HEAL_IN_COMBAT_LIMIT"; | ||||
| // Variable to change the looting range. | ||||
| const string AI_LOOT_CHECK_RANGE = "AI_LOOT_CHECK_RANGE"; | ||||
| // Variable to change the lock checking range. | ||||
| const string AI_LOCK_CHECK_RANGE = "AI_LOCK_CHECK_RANGE"; | ||||
| // Variable to change the trap checking range. | ||||
| const string AI_TRAP_CHECK_RANGE = "AI_TRAP_CHECK_RANGE"; | ||||
| // Variable to change the range an associate follows the pc. | ||||
| const string AI_FOLLOW_RANGE = "AI_FOLLOW_RANGE"; | ||||
| // Variable that holds the target for an associate to follow. | ||||
| const string AI_FOLLOW_TARGET = "AI_FOLLOW_TARGET"; | ||||
| // Variable that holds the perception range of associates i.e. 8, 9, 10, 11. | ||||
| const string AI_ASSOCIATE_PERCEPTION = "AI_PERCEPTION_RANGE"; | ||||
| // Variable that holds the perception distance of associates i.e. 30.0 meters. | ||||
| const string AI_ASSOC_PERCEPTION_DISTANCE = "AI_ASSOC_PERCEPTION_DISTANCE"; | ||||
| // Variable that holds the open doors range of the henchman. | ||||
| const string AI_OPEN_DOORS_RANGE = "AI_OPEN_DOORS_RANGE"; | ||||
| // Variable that holds the Spell widgets json data. | ||||
| const string AI_SPELLS_WIDGET = "AI_SPELLS_WIDGET"; | ||||
| // The number of Buff Groups | ||||
| const int AI_BUFF_GROUPS = -17; | ||||
| // Variable name used to keep track if we have set our talents. | ||||
| const string AI_TALENTS_SET = "AI_TALENTS_SET"; | ||||
| // New talent categories | ||||
| const string AI_TALENT_ENHANCEMENT        = "E"; | ||||
| const string AI_TALENT_PROTECTION         = "P"; | ||||
| const string AI_TALENT_SUMMON             = "S"; | ||||
| const string AI_TALENT_HEALING            = "H"; | ||||
| const string AI_TALENT_CURE               = "C"; | ||||
| const string AI_TALENT_INDISCRIMINANT_AOE = "I"; | ||||
| const string AI_TALENT_DISCRIMINANT_AOE   = "D"; | ||||
| const string AI_TALENT_RANGED             = "R"; | ||||
| const string AI_TALENT_TOUCH              = "T"; | ||||
| // Talent types. | ||||
| const int AI_TALENT_TYPE_SPELL = 1; | ||||
| const int AI_TALENT_TYPE_SP_ABILITY = 2; | ||||
| const int AI_TALENT_TYPE_FEAT = 3; | ||||
| const int AI_TALENT_TYPE_ITEM = 4; | ||||
| // Variable name used to have associates fight the pc's selected target. | ||||
| const string AI_PC_LOCKED_TARGET = "AI_PC_LOCKED_TARGET"; | ||||
| // Variable name of json talent immunity. | ||||
| const string AI_TALENT_IMMUNITY = "AI_TALENT_IMMUNITY"; | ||||
| // Variables keeps track of the maximum level for the talent category. | ||||
| const string AI_MAX_TALENT = "AI_MAX_TALENT_"; | ||||
| // Backward compatability constants. | ||||
| const int X2_EVENT_CONCENTRATION_BROKEN = 12400; | ||||
| // Variable set on the module if the module is using PRC. | ||||
| const string AI_USING_PRC = "AI_USING_PRC"; | ||||
| // Variable that sets if the rules have been added to the module. | ||||
| const string AI_RULES_SET = "AI_RULES_SET"; | ||||
| // Variable that tells us that oCreature has run our OnSpawn event. | ||||
| const string AI_ONSPAWN_EVENT = "AI_ONSPAWN_EVENT"; | ||||
| // Variable used to define a creatures unique Tag for widgets. | ||||
| const string AI_TAG = "AI_TAG"; | ||||
| // Variable that saves any module target event script so we can pass it along. | ||||
| const string AI_MODULE_TARGET_EVENT = "AI_MODULE_TARGET_EVENT"; | ||||
| // Variable for plugins to inject Targeting mode code into PEPS. | ||||
| const string AI_PLUGIN_TARGET_SCRIPT = "AI_PLUGIN_TARGET_SCRIPT"; | ||||
| // Variable for PEPS to inject effect icons NUI information. | ||||
| const string AI_MODULE_GUI_EVENT = "AI_MODULE_GUI_EVENT"; | ||||
| // Variable used on the player to define the targeting action in the OnPlayerTarget event script. | ||||
| const string AI_TARGET_MODE = "AI_TARGET_MODE"; | ||||
| // Variable used on the player to define which associate triggered the OnPlayer Target. | ||||
| const string AI_TARGET_ASSOCIATE = "AI_TARGET_ASSOCIATE"; | ||||
| // Bitwise constants for immune damage item properties that is used with Get/SetItemProperty(). | ||||
| const string sIPImmuneVarname = "AI_IP_IMMUNE"; | ||||
| // Bitwise constants for resisted damage item properties that is used with Get/SetItemProperty(). | ||||
| const string sIPResistVarname = "AI_IP_RESIST"; | ||||
| // Variable name for the Int constant for reduced damage item property set to the bonus of the weapon required. | ||||
| const string sIPReducedVarname = "AI_IP_REDUCED"; | ||||
| // Variable name for the Int (Bool) constant for the haste item property. | ||||
| const string sIPHasHasteVarname = "AI_IP_HAS_HASTE"; | ||||
| // Variable name used to hold the party xp base needed to adjust party xp. | ||||
| const string AI_BASE_PARTY_SCALE_XP = "AI_BASE_PARTY_SCALE_XP"; | ||||
| //***************************** AI RULES CONSTANTS ***************************** | ||||
| // Variable name set to a creatures full name to set debugging on. | ||||
| const string AI_RULE_DEBUG_CREATURE = "AI_RULE_DEBUG_CREATURE"; | ||||
| // Moral checks on or off. | ||||
| const string AI_RULE_MORAL_CHECKS = "AI_RULE_MORAL_CHECKS"; | ||||
| // Allows monsters to prebuff before combat starts. | ||||
| const string AI_RULE_BUFF_MONSTERS = "AI_RULE_BUFF_MONSTERS"; | ||||
| // Allows monsters to use the ambush AI scripts. | ||||
| const string AI_RULE_AMBUSH = "AI_RULE_AMBUSH"; | ||||
| // Enemies may summon familiars and Animal companions and will be randomized. | ||||
| const string AI_RULE_SUMMON_COMPANIONS = "AI_RULE_SUMMON_COMPANIONS"; | ||||
| // Allows monsters cast summons spells when prebuffing. | ||||
| const string AI_RULE_PRESUMMON = "AI_RULE_PRESUMMON"; | ||||
| // Allow the AI move during combat base on the situation and action taking. | ||||
| const string AI_RULE_ADVANCED_MOVEMENT = "AI_RULE_ADVANCED_MOVEMENT"; | ||||
| // Follow Item Level Restrictions for monsters/associates. | ||||
| // Usually off in Single player and on in Multi player. | ||||
| const string AI_RULE_ILR = "AI_RULE_ILR"; | ||||
| // Allow the AI to use Use Magic Device. | ||||
| const string AI_RULE_ALLOW_UMD = "AI_RULE_ALLOW_UMD"; | ||||
| // Allow the AI to use healing kits. | ||||
| const string AI_RULE_HEALERSKITS = "AI_RULE_HEALERSKITS"; | ||||
| // Summoned associates are permanent and don't disappear when the caster dies. | ||||
| const string AI_RULE_PERM_ASSOC = "AI_RULE_PERM_ASSOC"; | ||||
| // Monster AI's chance to attack the weakest target instead of the nearest. | ||||
| const string AI_RULE_AI_DIFFICULTY = "AI_RULE_AI_DIFFICULTY"; | ||||
| // Variable that can change the distance creatures will come and attack after | ||||
| // hearing a shout from an ally that sees or hears an enemy. | ||||
| // Or when searching for an invisible, heard enemy. | ||||
| // 10.0 Short, 30.0 Average, 40.0 Long, 60.0 Huge. | ||||
| const string AI_RULE_PERCEPTION_DISTANCE = "AI_RULE_PERCEPTION_DISTANCE"; | ||||
| // Enemy corpses remain on the floor instead of dissappearing. | ||||
| const string AI_RULE_CORPSES_STAY = "AI_RULE_CORPSES_STAY"; | ||||
| // Monsters will wander around when not in combat. | ||||
| const string AI_RULE_WANDER = "AI_RULE_WANDER"; | ||||
| // Increase the number of encounter creatures. | ||||
| const string AI_INCREASE_ENC_MONSTERS = "AI_INCREASE_ENC_MONSTERS"; | ||||
| // Increase all monsters hitpoints by this percentage. | ||||
| const string AI_INCREASE_MONSTERS_HP = "AI_INCREASE_MONSTERS_HP"; | ||||
| // Variable that can change the distance monsters can hear and see. | ||||
| const string AI_RULE_MON_PERC_DISTANCE = "AI_RULE_MON_PERC_DISTANCE"; | ||||
| // Variable name set to hold the maximum number of henchman the player wants. | ||||
| const string AI_RULE_MAX_HENCHMAN = "AI_RULE_MAX_HENCHMAN"; | ||||
| // Variable name set to hold the distance monsters can wander away. | ||||
| const string AI_RULE_WANDER_DISTANCE = "AI_RULE_WANDER_DISTANCE"; | ||||
| // Variable name set to allow wandering monsters to open doors. | ||||
| const string AI_RULE_OPEN_DOORS = "AI_RULE_OPEN_DOORS"; | ||||
| // Variable name set to hold the modules default xp scale for use later. | ||||
| const string AI_RULE_DEFAULT_XP_SCALE = "AI_RULE_DEFAULT_XP_SCALE"; | ||||
| // Variable name set to allow the game to regulate experience based on party size. | ||||
| const string AI_RULE_PARTY_SCALE = "AI_RULE_PARTY_SCALE"; | ||||
| // Variable name set to restrict the AI's use of Darkness. | ||||
| const string AI_RULE_RESTRICTED_SPELLS = "AI_RULE_RESTRICTED_SPELLS"; | ||||
| /*/ Special behavior constants from x0_i0_behavior | ||||
| const int NW_FLAG_BEHAVIOR_SPECIAL       = 0x00000001; | ||||
| //Will always attack regardless of faction | ||||
| const int NW_FLAG_BEHAVIOR_CARNIVORE     = 0x00000002; | ||||
| //Will only attack if approached | ||||
| const int NW_FLAG_BEHAVIOR_OMNIVORE      = 0x00000004; | ||||
| //Will never attack.  Will alway flee. | ||||
| const int NW_FLAG_BEHAVIOR_HERBIVORE     = 0x00000008; | ||||
| // This is the name of the local variable that holds the spawn-in conditions | ||||
| const string sSpawnCondVarname = "NW_GENERIC_MASTER"; | ||||
| // The available spawn-in conditions from x0_i0_spawncond | ||||
| const int NW_FLAG_ESCAPE_RETURN               = 0x00000020; //Failed | ||||
| const int NW_FLAG_ESCAPE_LEAVE                = 0x00000040; | ||||
| const int NW_FLAG_TELEPORT_RETURN             = 0x00000080; //Failed | ||||
| const int NW_FLAG_TELEPORT_LEAVE              = 0x00000100; | ||||
| const int NW_FLAG_END_COMBAT_ROUND_EVENT      = 0x00004000; | ||||
| const int NW_FLAG_ON_DIALOGUE_EVENT           = 0x00008000; | ||||
| const int NW_FLAG_AMBIENT_ANIMATIONS          = 0x00080000; | ||||
| const int NW_FLAG_HEARTBEAT_EVENT             = 0x00100000; | ||||
| const int NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS = 0x00200000; | ||||
| const int NW_FLAG_DAY_NIGHT_POSTING           = 0x00400000; | ||||
| const int NW_FLAG_AMBIENT_ANIMATIONS_AVIAN    = 0x00800000; | ||||
| const string sWalkwayVarname = "NW_WALK_CONDITION"; | ||||
| // If set, the creature's waypoints have been initialized. | ||||
| const int NW_WALK_FLAG_INITIALIZED                 = 0x00000001; | ||||
| // If set, the creature will walk its waypoints constantly, | ||||
| // moving on in each OnHeartbeat event. Otherwise, | ||||
| // it will walk to the next only when triggered by an | ||||
| // OnPerception event. | ||||
| const int NW_WALK_FLAG_CONSTANT                    = 0x00000002; | ||||
| // Set when the creature is walking day waypoints. | ||||
| const int NW_WALK_FLAG_IS_DAY                      = 0x00000004; | ||||
| // Set when the creature is walking back | ||||
| const int NW_WALK_FLAG_BACKWARDS                   = 0x00000008; | ||||
							
								
								
									
										1032
									
								
								_module/nss/0i_gui_events.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1032
									
								
								_module/nss/0i_gui_events.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1243
									
								
								_module/nss/0i_items.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1243
									
								
								_module/nss/0i_items.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1347
									
								
								_module/nss/0i_main.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1347
									
								
								_module/nss/0i_main.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4935
									
								
								_module/nss/0i_menus.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4935
									
								
								_module/nss/0i_menus.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1386
									
								
								_module/nss/0i_menus_dm.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1386
									
								
								_module/nss/0i_menus_dm.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										88
									
								
								_module/nss/0i_messages.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								_module/nss/0i_messages.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0i_messages | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Include script for sending messages to files and players on the server. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_constants" | ||||
| #include "0i_color" | ||||
| // Sets up a Message on the module to be sent to the log and/or players. | ||||
| // sTextColor color of text sent to the players and DM's. | ||||
| // Use AI_COLOR_*. Where * is WHITE, RED, GREEN, BLUE, GRAY, or YELLOW. | ||||
| // If nLog is TRUE it will send the message to the log file. | ||||
| // If nToDMs is TRUE it will send the message to all DM's. | ||||
| // If oPC is set to a player then they will get the message as well. | ||||
| // Messages delivered by script should be colored as follows. | ||||
| // _Debug message = COLOR_WHITE | ||||
| // Generic messages for the player = AI_COLOR_YELLOW | ||||
| // Negative messages for the player = AI_COLOR_RED | ||||
| // Positive messages for the player = AI_COLOR_GREEN | ||||
| // System messages, things that are not part of Dnd = COLOR_GRAY | ||||
| // Descriptive in game messages = COLOR_BLUE | ||||
| void ai_SendMessages(string sMessage, string sTextColor = AI_COLOR_YELLOW, object oPC = OBJECT_INVALID, int nToDMs = FALSE, int nLog = FALSE); | ||||
| // Used for _debugging. Keeps all the information organized. | ||||
| // Sends info to first pc if true and sends information to log file. | ||||
| // sScriptName is the name of the script calling this function. | ||||
| // sLineNumber is the line number of the code calling this function. | ||||
| // sMessage is the description of the debug being sent. | ||||
| void ai_Debug(string sScriptName, string sLineNumber, string sMessage); | ||||
| // A counter to track microseconds in code. Start saves the counter. | ||||
| void ai_Counter_Start(); | ||||
| // A counter to track microseconds in code. End displays the time between Start | ||||
| // and End to the log file. | ||||
| void ai_Counter_End(string sMessage = ""); | ||||
|  | ||||
| void ai_SendMessages(string sMessage, string sTextColor = AI_COLOR_YELLOW, object oPC = OBJECT_INVALID, int nToDMs = FALSE, int nLog = FALSE) | ||||
| { | ||||
|     // if nLog is TRUE send the message to the log file. | ||||
|     if(nLog) | ||||
|     { | ||||
|         sMessage = ai_StripColorCodes(sMessage); | ||||
|         // Add PC name to log to know who it belongs to. | ||||
|         string sLogPCName; | ||||
|         if(oPC != OBJECT_INVALID) sLogPCName = "(" + GetName(oPC) + ") "; | ||||
|         WriteTimestampedLogEntry("*** MESSAGE: " + sLogPCName + " " + sMessage); | ||||
|     } | ||||
|     sMessage = ai_AddColorToText(sMessage, sTextColor); | ||||
|     if(oPC != OBJECT_INVALID) SendMessageToPC(oPC, sMessage); | ||||
|     // If nToDMs is true send message to the DM's online. | ||||
|     if(nToDMs) SendMessageToAllDMs(sMessage); | ||||
| } | ||||
| void ai_Debug(string sScriptName, string sLineNumber, string sMessage) | ||||
| { | ||||
|     string sName = GetName(OBJECT_SELF); | ||||
|     if(sName == GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE) && | ||||
|        sName != "") | ||||
|     { | ||||
|         sMessage = "(((DEBUG)))[" + sScriptName + " - " + sLineNumber + " ]" + sMessage; | ||||
|         sMessage = ai_StripColorCodes(sMessage); | ||||
|         WriteTimestampedLogEntry(sMessage); | ||||
|         return; | ||||
|     } | ||||
|     //sMessage = "(((DEBUG)))[" + sScriptName + " - " + sLineNumber + " ]" + sMessage; | ||||
|     //sMessage = ai_StripColorCodes(sMessage); | ||||
|     //SendMessageToPC(GetFirstPC(), sMessage); | ||||
|     //WriteTimestampedLogEntry(sMessage); | ||||
|     //if(GetLocalInt(OBJECT_SELF, "AI_DEBUG")) WriteTimestampedLogEntry(sMessage); | ||||
|     //if(GetName(OBJECT_SELF) == "Kirrin") WriteTimestampedLogEntry(sMessage); | ||||
|     //if(GetName(OBJECT_SELF) == "Dorna Trapspringer") WriteTimestampedLogEntry(sMessage); | ||||
|     //if(GetName(OBJECT_SELF) == "Dire Spider") WriteTimestampedLogEntry(sMessage); | ||||
|     //if(GetName(OBJECT_SELF) == "Shadow Priest") WriteTimestampedLogEntry(sMessage); | ||||
|     //if(GetName(OBJECT_SELF) == "Tomi Undergallows") WriteTimestampedLogEntry(sMessage); | ||||
|     //if(GetName(OBJECT_SELF) == "Thello Colds") WriteTimestampedLogEntry(sMessage); | ||||
|     //if(GetName(OBJECT_SELF) == "Gert Sigers") WriteTimestampedLogEntry(sMessage); | ||||
|     //if(GetName(OBJECT_SELF) == "Zombie") WriteTimestampedLogEntry(sMessage); | ||||
| } | ||||
| void ai_Counter_Start() | ||||
| { | ||||
|     SetLocalInt(GetModule(), "0_MSCounter", GetMicrosecondCounter()); | ||||
| } | ||||
| void ai_Counter_End(string sMessage = "") | ||||
| { | ||||
|     int nTime = GetMicrosecondCounter(); | ||||
|     nTime = nTime - GetLocalInt(GetModule(), "0_MSCounter"); | ||||
|     float fTime = nTime / 1000000.0; | ||||
|     if(AI_DEBUG) ai_Debug("MICROSECOND_COUNTER", "", "Seconds: " + FloatToString(fTime, 0, 10) + | ||||
|              " Microseconds: " + IntToString(nTime) + " " + sMessage); | ||||
| } | ||||
							
								
								
									
										544
									
								
								_module/nss/0i_module.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										544
									
								
								_module/nss/0i_module.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,544 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0i_module | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Include script for handling event scripts for injecting the systems into a | ||||
|  module for either single player or a server. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "x2_inc_switches" | ||||
| #include "0i_associates" | ||||
| #include "0i_menus" | ||||
| #include "0i_player_target" | ||||
| #include "0i_gui_events" | ||||
| // Add to nw_c2_default9 OnSpawn event script of monsters and | ||||
| int ai_OnMonsterSpawn(object oCreature); | ||||
| // Add to nw_ch_ac9 OnSpawn event script of henchman. | ||||
| void ai_OnAssociateSpawn(object oCreature); | ||||
| // Run all of the players starting scripts. | ||||
| // If oPC is passed as Invalid then it will get the firt PC in the game. | ||||
| void ai_CheckPCStart(object oPC = OBJECT_INVALID); | ||||
| // Checks to see if we should change the monster via Json. | ||||
| int ai_ChangeMonster(object oCreature, object oModule); | ||||
| // Checks to see if we should change the associate via Json. | ||||
| object ai_ChangeAssociate(object oCreature, object oModule); | ||||
| // Sets the events for oCreature that is a Monster while playing Infinite Dungeons. | ||||
| void ai_SetIDMonsterEventScripts(object oCreature); | ||||
| // Sets the events for oCreature that is a monster in while using the PRC and | ||||
| // playing Infinite Dungeons. | ||||
| void ai_SetPRCIDMonsterEventScripts(object oCreature); | ||||
| // Sets the events for oCreature that is an associate while using the PRC. | ||||
| void ai_SetPRCAssociateEventScripts(object oCreature); | ||||
| // Reverts single player monster event scripts back to their default. | ||||
| void ai_ChangeEventScriptsForMonster(object oCreature); | ||||
| // Reverts single player associates event scripts back to their default. | ||||
| void ai_ChangeEventScriptsForAssociate(object oCreature); | ||||
| // If using PRC this will replace some spells with PRC variants. | ||||
| json ai_ReplaceSpellsWithPRCVariants(object oCreature, json jCreature); | ||||
|  | ||||
| //****************************************************************************** | ||||
| //********************* Creature event scripts ********************************* | ||||
| //****************************************************************************** | ||||
| int ai_OnMonsterSpawn(object oCreature) | ||||
| { | ||||
|     if(GetLocalInt(oCreature, AI_ONSPAWN_EVENT)) return FALSE; | ||||
|     SetLocalInt(oCreature, AI_ONSPAWN_EVENT, TRUE); | ||||
|     object oModule = GetModule(); | ||||
|     int nInfiniteDungeons; | ||||
|     int nPRC = GetLocalInt(oModule, AI_USING_PRC); | ||||
|     // If you are running a server this will not affect the module. | ||||
|     if(!AI_SERVER) | ||||
|     { | ||||
|         ai_CheckPCStart(); | ||||
|         string sModuleName = GetModuleName(); | ||||
|         if(sModuleName == "Neverwinter Nights - Infinite Dungeons" || | ||||
|            sModuleName == "Infinite Dungeons [PRC8]") | ||||
|         { | ||||
|             nInfiniteDungeons = TRUE; | ||||
|             if(nPRC) ai_SetPRCIDMonsterEventScripts(oCreature); | ||||
|             else ai_SetIDMonsterEventScripts(oCreature); | ||||
|             // Fix to get plot givers, finishers from getting killed a lot. | ||||
|             if(GetLocalString(oCreature, "sConversation") == "id1_plotgiver " || | ||||
|                GetLocalString(oCreature, "sConversation") == "id1_plotdest") | ||||
|             { | ||||
|                 ChangeToStandardFaction(oCreature, STANDARD_FACTION_MERCHANT); | ||||
|                 SetStandardFactionReputation(STANDARD_FACTION_HOSTILE, 50, oCreature); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     // PRC and Infinite dungeons has issues with Ondeath script so we just leave it alone. | ||||
|     if(!nPRC && !nInfiniteDungeons) | ||||
|     { | ||||
|         // We change this script so we can setup permanent summons on/off. | ||||
|         string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH); | ||||
|         SetLocalString(oCreature, "AI_ON_DEATH", sScript); | ||||
|         SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_c2_7_ondeath"); | ||||
|     } | ||||
|     if(GetCreatureFlag(oCreature, CREATURE_VAR_IS_INCORPOREAL)) | ||||
|     { | ||||
|         string sCombatAI = GetLocalString(oCreature, AI_DEFAULT_SCRIPT); | ||||
|         if (sCombatAI == "") SetLocalString(oCreature, AI_DEFAULT_SCRIPT, "ai_incorporeal"); | ||||
|     } | ||||
|     ai_SetListeningPatterns(oCreature); | ||||
|     ai_SetCreatureAIScript(oCreature); | ||||
|     ai_SetNormalAppearance(oCreature); | ||||
|     ai_SetAura(oCreature); | ||||
|     SetLocalInt(oCreature, AI_HEAL_IN_COMBAT_LIMIT, AI_MONSTER_HEAL_IN_COMBAT_CHANCE); | ||||
|     SetLocalInt(oCreature, AI_HEAL_OUT_OF_COMBAT_LIMIT, AI_MONSTER_HEAL_OUT_COMBAT_CHANCE); | ||||
|     int nMonsterHpIncrease = GetLocalInt(oModule, AI_INCREASE_MONSTERS_HP); | ||||
|     if(nMonsterHpIncrease) | ||||
|     { | ||||
|         int nHp = GetMaxHitPoints(oCreature); | ||||
|         nHp = (nHp * nMonsterHpIncrease) / 100; | ||||
|         effect eHp = EffectTemporaryHitpoints(nHp); | ||||
|         eHp = SupernaturalEffect(eHp); | ||||
|         ApplyEffectToObject(DURATION_TYPE_PERMANENT, eHp, oCreature); | ||||
|     } | ||||
|     // Check if the monster should change how they search for targets. | ||||
|     if(d100() <= GetLocalInt(GetModule(), AI_RULE_AI_DIFFICULTY)) | ||||
|     { | ||||
|         SetLocalInt(oCreature, AI_RULE_AI_DIFFICULTY, TRUE); | ||||
|     } | ||||
|     // Do json changes after we have setup the creature. | ||||
|     if(ai_ChangeMonster(oCreature, oModule)) return TRUE; | ||||
|     return FALSE; | ||||
| } | ||||
| void ai_OnAssociateSpawn(object oCreature) | ||||
| { | ||||
|     if(GetLocalInt(oCreature, AI_ONSPAWN_EVENT)) return; | ||||
|     SetLocalInt(oCreature, AI_ONSPAWN_EVENT, TRUE); | ||||
|     int bPRC = GetLocalInt(GetModule(), AI_USING_PRC); | ||||
|     // If you are running a server this will not affect the module. | ||||
|     if(!AI_SERVER) | ||||
|     { | ||||
|         if(bPRC) ai_SetPRCAssociateEventScripts(oCreature); | ||||
|     } | ||||
|     // PRC has issues with Ondeath script so we just leave it alone. | ||||
|     if(!bPRC) | ||||
|     { | ||||
|         // We change this script so we can setup permanent summons on/off. | ||||
|         // If you don't use this you may remove the next three lines. | ||||
|         string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH); | ||||
|         SetLocalString(oCreature, "AI_ON_DEATH", sScript); | ||||
|         SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_ch_7_ondeath"); | ||||
|     } | ||||
|     // Initialize Associate modes for basic use. | ||||
|     ai_SetListeningPatterns(oCreature); | ||||
|     ai_SetNormalAppearance(oCreature); | ||||
|     ai_SetAssociateAIScript(oCreature, FALSE); | ||||
|     ai_SetAura(oCreature); | ||||
|     if(GetLocalInt(GetModule(), AI_RULE_PARTY_SCALE)) ai_CheckXPPartyScale(oCreature); | ||||
|     // Bioware summoned shadows are not incorporeal, also set the ai code. | ||||
|     if (GetTag(OBJECT_SELF) == "NW_S_SHADOW") | ||||
|     { | ||||
|         SetLocalInt(OBJECT_SELF, "X2_L_IS_INCORPOREAL", TRUE); | ||||
|         SetLocalString(OBJECT_SELF, AI_DEFAULT_SCRIPT, "ai_shadow"); | ||||
|     } | ||||
| } | ||||
| void ai_CheckPCStart(object oPC = OBJECT_INVALID) | ||||
| { | ||||
|     if(oPC == OBJECT_INVALID) oPC = GetFirstPC(); | ||||
|     // There should always be a PC widget. If it doesn't exist then we assume | ||||
|     // that the module is being loaded or started. | ||||
|     if(!NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)) | ||||
|     { | ||||
|         object oModule = GetModule(); | ||||
|         // Do PRC check and save variable to the module. | ||||
|         if(ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS) != "") | ||||
|             SetLocalInt(oModule, AI_USING_PRC, TRUE); | ||||
|         ai_SetAIRules(); | ||||
|         ai_CheckAssociateData(oPC, oPC, "pc"); | ||||
|         ai_StartupPlugins(oPC); | ||||
|         ai_SetupPlayerTarget(oPC); | ||||
|         ai_SetupModuleGUIEvents(oPC); | ||||
|         ai_CreateWidgetNUI(oPC, oPC); | ||||
|         ai_SetNormalAppearance(oPC); | ||||
|     } | ||||
| } | ||||
| void ai_CopyMonster(object oCreature, object oModule) | ||||
| { | ||||
|     // After setting the monster lets see if we should copy it. | ||||
|     float fMonsterIncrease = GetLocalFloat(oModule, AI_INCREASE_ENC_MONSTERS); | ||||
|     if(GetIsEncounterCreature(oCreature) && fMonsterIncrease > 0.0) | ||||
|     { | ||||
|         int nMonsterIncrease; | ||||
|         float fMonsterCounter = GetLocalFloat(oModule, "AI_MONSTER_COUNTER"); | ||||
|         fMonsterCounter += fMonsterIncrease; | ||||
|         nMonsterIncrease = FloatToInt(fMonsterCounter); | ||||
|         if(nMonsterIncrease > 0) | ||||
|         { | ||||
|            fMonsterCounter = fMonsterCounter - IntToFloat(nMonsterIncrease); | ||||
|         } | ||||
|         SetLocalFloat(oModule, "AI_MONSTER_COUNTER", fMonsterCounter); | ||||
|         while(nMonsterIncrease > 0) | ||||
|         { | ||||
|             CopyObject(oCreature, GetLocation(oCreature), OBJECT_INVALID, "", TRUE); | ||||
|             nMonsterIncrease = nMonsterIncrease - 1; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| void ai_CreateMonster(json jCreature, location lLocation, object oModule) | ||||
| { | ||||
|     //WriteTimestampedLogEntry("0i_module, 181, " + JsonDump(jCreature, 1)); | ||||
|     object oCreature = JsonToObject(jCreature, lLocation, OBJECT_INVALID, TRUE); | ||||
|     // Lets set the new version as spawned so we skip the initial setup again. | ||||
|     SetLocalInt(oCreature, AI_ONSPAWN_EVENT, TRUE); | ||||
|     /*if(GetLocalInt(oModule, AI_RULE_CORPSES_STAY)) | ||||
|     { | ||||
|         SetIsDestroyable(FALSE, FALSE, TRUE, oCreature); | ||||
|         SetLootable(oCreature, TRUE); | ||||
|     } */ | ||||
|     if(AI_DEBUG) ai_Debug("0i_module", "187", GetName(oCreature)); | ||||
|     ai_CopyMonster(oCreature, oModule); | ||||
|     return; | ||||
| } | ||||
| json ai_SetCompanionSummoning(object oCreature, json jCreature) | ||||
| { | ||||
|     if(GetHasFeat(FEAT_SUMMON_FAMILIAR, oCreature, TRUE)) | ||||
|     { | ||||
|         json jFamiliar = JsonObjectGet(jCreature, "FamiliarName"); | ||||
|         jFamiliar = JsonObjectSet(jFamiliar, "value", JsonString("Summoned Familiar")); | ||||
|         jCreature = JsonObjectSet(jCreature, "FamiliarName", jFamiliar); | ||||
|         jFamiliar = JsonObjectGet(jCreature, "FamiliarType"); | ||||
|         jFamiliar = JsonObjectSet(jFamiliar, "value", JsonInt(Random(11))); | ||||
|         return JsonObjectSet(jCreature, "FamiliarType", jFamiliar); | ||||
|     } | ||||
|     if(GetHasFeat(FEAT_ANIMAL_COMPANION , oCreature, TRUE)) | ||||
|     { | ||||
|         json jCompanion = JsonObjectGet(jCreature, "CompanionName"); | ||||
|         jCompanion = JsonObjectSet(jCompanion, "value", JsonString("Summoned Companion")); | ||||
|         jCreature = JsonObjectSet(jCreature, "CompanionName", jCompanion); | ||||
|         jCompanion = JsonObjectGet(jCreature, "CompanionType"); | ||||
|         jCompanion = JsonObjectSet(jCompanion, "value", JsonInt(Random(9))); | ||||
|         return JsonObjectSet(jCreature, "CompanionType", jCompanion); | ||||
|     } | ||||
|     return jCreature; | ||||
| } | ||||
| int ai_ChangeMonster(object oCreature, object oModule) | ||||
| { | ||||
|     object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oCreature); | ||||
|     // Lets not mess up the cutscenes with silly RULES. | ||||
|     if(GetCutsceneMode(oPC)) return FALSE; | ||||
|     //float fDistance = GetDistanceBetween(oCreature, oPC); | ||||
|     // Looks bad to see creatures wink in and out plus could cause module errors. | ||||
|     //if(fDistance != 0.0 && fDistance < AI_RANGE_PERCEPTION) return oCreature; | ||||
|     if(IsInConversation(oCreature)) return FALSE; | ||||
|     json jCreature = ObjectToJson(oCreature, TRUE); | ||||
|     // We now use plugins to mod our monsters. | ||||
|     json jMonsterMods = GetLocalJson(oModule, AI_MONSTER_MOD_JSON); | ||||
|     if(JsonGetType(jMonsterMods) != JSON_TYPE_NULL) | ||||
|     { | ||||
|         SetLocalJson(oModule, AI_MONSTER_JSON, jCreature); | ||||
|         SetLocalObject(oModule, AI_MONSTER_OBJECT, oCreature); | ||||
|         int nIndex; | ||||
|         string sMonsterMod = JsonGetString(JsonArrayGet(jMonsterMods, nIndex)); | ||||
|         while(sMonsterMod != "") | ||||
|         { | ||||
|             ExecuteScript(sMonsterMod, oPC); | ||||
|             sMonsterMod = JsonGetString(JsonArrayGet(jMonsterMods, ++nIndex)); | ||||
|         } | ||||
|         jCreature = GetLocalJson(oModule, AI_MONSTER_JSON); | ||||
|     } | ||||
|     int nSummon = GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS) && | ||||
|                  (GetHasFeat(FEAT_SUMMON_FAMILIAR, oCreature, TRUE)) || | ||||
|                   GetHasFeat(FEAT_ANIMAL_COMPANION, oCreature, TRUE); | ||||
|     int nPercDist = GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE) != 11 && | ||||
|                     GetReputation(oCreature, oPC) < 11; | ||||
|     //WriteTimestampedLogEntry(GetName(oCreature) + ": fDistance: " + FloatToString(fDistance, 0, 2) + " nSummon: " + IntToString(nSummon) + | ||||
|     //      " nPercDist: " + IntToString(nPercDist) + " Reputation: " + IntToString(GetReputation(oCreature, oPC))); | ||||
|     if(nSummon || nPercDist) | ||||
|     { | ||||
|         location lLocation = GetLocation(oCreature); | ||||
|         if(nPercDist) | ||||
|         { | ||||
|             json jPerception = JsonObjectGet(jCreature, "PerceptionRange"); | ||||
|             jPerception = JsonObjectSet(jPerception, "value", JsonInt(GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE))); | ||||
|             jCreature = JsonObjectSet(jCreature, "PerceptionRange", jPerception); | ||||
|         } | ||||
|         if(nSummon) jCreature = ai_SetCompanionSummoning(oCreature, jCreature); | ||||
|         SetLocalInt(oModule, AI_MONSTER_CHANGED, TRUE); | ||||
|     } | ||||
|     if(GetLocalInt(oModule, AI_MONSTER_CHANGED)) | ||||
|     { | ||||
|         SetIsDestroyable(TRUE, FALSE, FALSE, oCreature); | ||||
|         location lLocation = GetLocation(oCreature); | ||||
|         DestroyObject(oCreature); | ||||
|         AssignCommand(oModule, DelayCommand(1.0, ai_CreateMonster(jCreature, lLocation, oModule))); | ||||
|         DeleteLocalInt(oModule, AI_MONSTER_CHANGED); | ||||
|         return TRUE; | ||||
|     } | ||||
|     else ai_CopyMonster(oCreature, oModule); | ||||
|     DeleteLocalJson(oModule, AI_MONSTER_JSON); | ||||
|     DeleteLocalObject(oModule, AI_MONSTER_OBJECT); | ||||
|     return FALSE; | ||||
| } | ||||
| // Special event scripts for Infinite Dungeons! | ||||
| void ai_SetIDMonsterEventScripts(object oCreature) | ||||
| { | ||||
|     //if(AI_DEBUG) ai_Debug("0i_module", "433", "Changing " + GetName(oCreature) + "'s Infinte Dungeons event scripts."); | ||||
|     //********** On Heartbeat ********** | ||||
|     string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT); | ||||
|     SetLocalString(oCreature, "AI_ON_HEARTBEAT", sScript); | ||||
|     if(sScript == "x2_def_heartbeat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_default1") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_HEARTBEAT SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Perception ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE); | ||||
|     SetLocalString(oCreature, "AI_ON_NOTICE", sScript); | ||||
|     if(sScript == "x2_def_percept") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_default2") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_NOTICE SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On End Combat Round ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND); | ||||
|     SetLocalString(oCreature, "AI_ON_END_COMBATROUND", sScript); | ||||
|     if(sScript == "x2_def_endcombat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_default3") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_END_COMBATROUND SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Dialogue ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE); | ||||
|     SetLocalString(oCreature, "AI_ON_DIALOGUE", sScript); | ||||
|     if(sScript == "x2_def_onconv") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_default4") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_DIALOGUE_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Melee Attacked ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED); | ||||
|     SetLocalString(oCreature, "AI_ON_MELEE_ATTACKED", sScript); | ||||
|     if(sScript == "x2_def_attacked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_default5") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_MELEE_ATTACKED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Damaged ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED); | ||||
|     SetLocalString(oCreature, "AI_ON_DAMAGED", sScript); | ||||
|     if(sScript == "x2_def_ondamage") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_default6") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_DAMAGED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     // We don't set OnDeath for Infinite Dungeons! | ||||
|     //********** On Death ********** | ||||
|     //sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH); | ||||
|     //SetLocalString(oCreature, "AI_ON_DEATH", sScript); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_id_events"); | ||||
|     //********** On Disturbed ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED); | ||||
|     SetLocalString(oCreature, "AI_ON_DISTURBED", sScript); | ||||
|     if(sScript == "x2_def_ondisturb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_default8") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_DISTURBED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, ""); | ||||
|     //********** On Rested ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED); | ||||
|     SetLocalString(oCreature, "AI_ON_RESTED", sScript); | ||||
|     if(sScript == "x2_def_rested") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_defaulta") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_RESTED SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Spell Cast At ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT); | ||||
|     SetLocalString(oCreature, "AI_ON_SPELLCASTAT", sScript); | ||||
|     if(sScript == "x2_def_spellcast") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_defaultb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_SPELLCASTAT_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Blocked ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR); | ||||
|     SetLocalString(oCreature, "AI_ON_BLOCKED_BY_DOOR", sScript); | ||||
|     if(sScript == "x2_def_onblocked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_id_events"); | ||||
|     else if(sScript == "nw_c2_defaulte") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_BLOCKED_BY_DOOR SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, ""); | ||||
| } | ||||
| // Special event scripts for Infinite Dungeons with PRC! | ||||
| void ai_SetPRCIDMonsterEventScripts(object oCreature) | ||||
| { | ||||
|     //if(AI_DEBUG) ai_Debug("0i_module", "433", "Changing " + GetName(oCreature) + "'s Infinte Dungeons event scripts for PRC."); | ||||
|     //********** On Heartbeat ********** | ||||
|     string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT); | ||||
|     SetLocalString(oCreature, "AI_ON_HEARTBEAT", sScript); | ||||
|     if(sScript == "x2_def_heartbeat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_default1") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_HEARTBEAT SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Perception ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE); | ||||
|     SetLocalString(oCreature, "AI_ON_NOTICE", sScript); | ||||
|     if(sScript == "x2_def_percept") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_default2") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_NOTICE SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On End Combat Round ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND); | ||||
|     SetLocalString(oCreature, "AI_ON_END_COMBATROUND", sScript); | ||||
|     if(sScript == "x2_def_endcombat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_default3") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_END_COMBATROUND SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Dialogue ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE); | ||||
|     SetLocalString(oCreature, "AI_ON_DIALOGUE", sScript); | ||||
|     if(sScript == "x2_def_onconv") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_default4") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_DIALOGUE_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Melee Attacked ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED); | ||||
|     SetLocalString(oCreature, "AI_ON_MELEE_ATTACKED", sScript); | ||||
|     if(sScript == "x2_def_attacked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_default5") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_MELEE_ATTACKED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Damaged ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED); | ||||
|     SetLocalString(oCreature, "AI_ON_DAMAGED", sScript); | ||||
|     if(sScript == "x2_def_ondamage") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_default6") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_DAMAGED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     // We don't set OnDeath for PRC or Infinite dungeons. | ||||
|     //********** On Death ********** | ||||
|     //sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH); | ||||
|     //SetLocalString(oCreature, "AI_ON_DEATH", sScript); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_prc_id_events"); | ||||
|     //********** On Disturbed ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED); | ||||
|     SetLocalString(oCreature, "AI_ON_DISTURBED", sScript); | ||||
|     if(sScript == "x2_def_ondisturb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_default8") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_DISTURBED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, ""); | ||||
|     //********** On Rested ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED); | ||||
|     SetLocalString(oCreature, "AI_ON_RESTED", sScript); | ||||
|     if(sScript == "x2_def_rested") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_defaulta") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_RESTED SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Spell Cast At ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT); | ||||
|     SetLocalString(oCreature, "AI_ON_SPELLCASTAT", sScript); | ||||
|     if(sScript == "x2_def_spellcast") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_defaultb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_SPELLCASTAT_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //********** On Blocked ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR); | ||||
|     SetLocalString(oCreature, "AI_ON_BLOCKED_BY_DOOR", sScript); | ||||
|     if(sScript == "x2_def_onblocked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_prc_id_events"); | ||||
|     else if(sScript == "nw_c2_defaulte") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_prc_id_events"); | ||||
|     else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events"); | ||||
|     else WriteTimestampedLogEntry("ON_BLOCKED_BY_DOOR SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + "."); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, ""); | ||||
| } | ||||
| // Special event scripts for PRC associates! | ||||
| void ai_SetPRCAssociateEventScripts(object oCreature) | ||||
| { | ||||
|     //if(AI_DEBUG) ai_Debug("0i_module", "433", "Changing " + GetName(oCreature) + "'s Infinte Dungeons event scripts for PRC."); | ||||
|     //********** On Heartbeat ********** | ||||
|     string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT); | ||||
|     SetLocalString(oCreature, "AI_ON_HEARTBEAT", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_ac1") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_prc_ch_events"); | ||||
|     //********** On Perception ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE); | ||||
|     SetLocalString(oCreature, "AI_ON_NOTICE", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_ac2") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_prc_ch_events"); | ||||
|     //********** On End Combat Round ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND); | ||||
|     SetLocalString(oCreature, "AI_ON_END_COMBATROUND", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_ac3") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_prc_ch_events"); | ||||
|     //********** On Dialogue ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE); | ||||
|     SetLocalString(oCreature, "AI_ON_DIALOGUE", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_ac4") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_prc_ch_events"); | ||||
|     //********** On Melee Attacked ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED); | ||||
|     SetLocalString(oCreature, "AI_ON_MELEE_ATTACKED", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_ac5") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_prc_ch_events"); | ||||
|     //********** On Damaged ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED); | ||||
|     SetLocalString(oCreature, "AI_ON_DAMAGED", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_ac6") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_prc_ch_events"); | ||||
|     //********** On Disturbed ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED); | ||||
|     SetLocalString(oCreature, "AI_ON_DISTURBED", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_ac8") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_prc_ch_events"); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, ""); | ||||
|     //********** On Rested ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED); | ||||
|     SetLocalString(oCreature, "AI_ON_RESTED", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_aca") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_prc_ch_events"); | ||||
|     //********** On Spell Cast At ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT); | ||||
|     SetLocalString(oCreature, "AI_ON_SPELLCASTAT", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_acb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_prc_ch_events"); | ||||
|     //********** On Blocked ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR); | ||||
|     SetLocalString(oCreature, "AI_ON_BLOCKED_BY_DOOR", sScript); | ||||
|     if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_prc_ch_events"); | ||||
|     else if(sScript == "nw_ch_ace") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_prc_ch_events"); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, ""); | ||||
|     if(!GetCommandable(oCreature)) SetCommandable(TRUE, oCreature); | ||||
| } | ||||
| void ai_ChangeEventScriptsForMonster(object oCreature) | ||||
| { | ||||
|     //********** On Heartbeat ********** | ||||
|     string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT); | ||||
|     if(sScript == "0e_c2_1_hb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "nw_c2_default1"); | ||||
|     //********** On Perception ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE); | ||||
|     if(sScript == "0e_c2_2_percept") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "nw_c2_default2"); | ||||
|     //********** On End Combat Round ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND); | ||||
|     if(sScript == "0e_c2_3_endround") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "nw_c2_default3"); | ||||
|     //********** On Dialogue ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE); | ||||
|     if(sScript == "0e_c2_4_convers") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "nw_c2_default4"); | ||||
|     //********** On Melee Attacked ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED); | ||||
|     if(sScript == "0e_c2_5_phyatked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "nw_c2_default5"); | ||||
|     //********** On Damaged ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED); | ||||
|     if(sScript == "0e_c2_6_damaged") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "nw_c2_default6"); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "nw_c2_deafult7"); | ||||
|     //********** On Disturbed ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED); | ||||
|     if(sScript == "0e_c2_8_disturb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "nw_c2_default8"); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, ""); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "nw_c2_defaulta"); | ||||
|     //********** On Spell Cast At ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT); | ||||
|     if(sScript == "0e_c2_b_castat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "nw_c2_defaultb"); | ||||
|     //********** On Blocked ********** | ||||
|     sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR); | ||||
|     if(sScript == "0e_c2_e_blocked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "nw_c2_defaulte"); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "nw_c2_defaulte"); | ||||
| } | ||||
| void ai_ChangeEventScriptsForAssociate(object oCreature) | ||||
| { | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "nw_ch_ac1"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "nw_ch_ac2"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "nw_ch_ac3"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "nw_ch_ac4"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "nw_ch_ac5"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "nw_ch_ac6"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "nw_ch_ac7"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "nw_ch_ac8"); | ||||
|     //SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, ""); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "nw_ch_aca"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "nw_ch_acb"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "nw_ch_ace"); | ||||
|     SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "nw_ch_acd"); | ||||
| } | ||||
							
								
								
									
										434
									
								
								_module/nss/0i_nui.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								_module/nss/0i_nui.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,434 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0i_nui | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Include script for handling window displays. | ||||
|  | ||||
|  Use the following to get/set window information. | ||||
|  string sBind = NuiGetNthBind (oPlayer, nToken, FALSE, #); | ||||
|  json jMenuInfo = NuiGetBind (oPlayer, nToken, sBind); | ||||
|  # Gets json information for window : | ||||
|  0 - string - "window_title" | ||||
|  1 - json - "window_geometry" : "h", "w", "x", "y" | ||||
|  2 - bool - "window_resizable" | ||||
|  3 - bool - "window_closable" | ||||
|  4 - bool - "window_transparent" | ||||
|  5 - bool - "window_border" | ||||
|  | ||||
|  Layout pixel sizes: | ||||
|  Pixel height Title bar 33. | ||||
|  Pixel height Top border 10, between widgets 8, bottom border 10. | ||||
|  Pixel width Left border 10, between widgets 4, right border 10. | ||||
|  | ||||
|  Group outer lines add 12 to the vertical and horizontal lines. | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_main" | ||||
| #include "nw_inc_nui" | ||||
| struct stComboBox | ||||
| { | ||||
|     json jIndex; | ||||
|     json jCombo; | ||||
|     json jRow; | ||||
|     json jResRefArray; | ||||
|     json jWinArray; | ||||
|     json jCanSummon; // Index of all the summons in summons.2da | ||||
| }; | ||||
|  | ||||
| // Saves the menu to the campaign database. | ||||
| void SaveMenuToCampaignDb(object oPC, int nToken, string sWndId); | ||||
| // Returns the middle of the screen for the x position. | ||||
| // oPC using the menu. | ||||
| // fMenuWidth - the width of the menu to display. | ||||
| float GetGUIWidthMiddle(object oPC, float fMenuWidth); | ||||
|  | ||||
| // Returns the middle of the screen for the y position. | ||||
| // oPC using the menu. | ||||
| // fMenuHeight - the height of the menu to display. | ||||
| float GetGUIHeightMiddle(object oPC, float fMenuHeight); | ||||
|  | ||||
| // Checks to see if sWndId is open. | ||||
| // If the window is open it removes it and returns FALSE | ||||
| // If the window is closed it returns TRUE | ||||
| int IsWindowClosed(object oPC, string sWndId); | ||||
|  | ||||
| // Returns the Window ID (nToken). | ||||
| // oPC is the PC using the menu. | ||||
| // jLayout is the Layout of the menu. | ||||
| // sWinID is the string ID for this window. | ||||
| // sTitle is the Title of the menu. | ||||
| // fX is the X position of the menu (-1.0: Centers, -2.0: UpperRight on Mouse, -3.0: Centers top of mouse). | ||||
| // fY is the Y position of the menu (-1.0: Centers, -2.0: UpperRight on Mouse, -3.0: Centers top of mouse). | ||||
| // fWidth is the width of the menu. | ||||
| // fHeight is the height of the menu. | ||||
| // bResize - TRUE will all it to be resized. | ||||
| // bCollapse - TRUE will allow the window to be collapsable. | ||||
| // bClose - TRUE will allow the window to be closed. | ||||
| // bTransparent - TRUE makes the menu transparent. | ||||
| // bBorder - TRUE makes the menu have a border. | ||||
| // sEventScript will fire this event script for this window. | ||||
| int SetWindow(object oPC, json jLayout, string sWinID, string sTitle, float fX, float fY, float fWidth, float fHeight, int bResize, int bCollapse, int bClose, int bTransparent, int bBorder, string sEventScript = ""); | ||||
|  | ||||
| // Creates a label element in jRow. | ||||
| // jRow is the row the label goes into. | ||||
| // sLabel is the text placed in the label. | ||||
| //     If "" is passed then it will create a bind of sId + "_label". | ||||
| // fWidth is the width of the label. | ||||
| // fHeight is the Height of the label. | ||||
| // nHAlign is horizonal align [NUI_HALING_*]. | ||||
| // nVAlign is vertial align [NUI_VALING_*]. | ||||
| // sId is the bind the event uses sId + "_event". | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateLabel(json jRow, string sLabel, string sId, float fWidth, float fHeight, int nHAlign = 0, int nVAlign = 0, float fMargin = -1.0, string sTooltip = ""); | ||||
|  | ||||
| // Creates a basic button element in jRow. | ||||
| // jRow is the row the label goes into. | ||||
| // sLabel is the text placed in the button. If "" is passed then it will | ||||
| // create a bind of sId + "_label". | ||||
| // sId is the binds for the button and the event uses sId + "_event". | ||||
| // fWidth is the width of the button. | ||||
| // fHeight is the Height of the button. | ||||
| // fMargin is the space around the button. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateButton(json jRow, string sLabel, string sId, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = ""); | ||||
|  | ||||
| // Creates a basic button select element in jRow. | ||||
| // jRow is the row the label goes into. | ||||
| // sLabel is the text placed in the button. If "" is passed then it will | ||||
| // create a bind of sId + "_label". | ||||
| // sId is the binds for the button and the event uses sId + "_event". | ||||
| // fWidth is the width of the button. | ||||
| // fHeight is the Height of the button. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateButtonSelect(json jRow, string sLabel, string sId, float fWidth, float fHeight, string sToolTip = ""); | ||||
|  | ||||
| // Creates a button element with an image in jRow. | ||||
| // jRow is the row the label goes into. | ||||
| // sImage is the resref of the image to use. | ||||
| //     If "" is passed then it will create a bind of sId + "_image". | ||||
| // sId is the binds for the button and the event uses sId + "_event". | ||||
| // fWidth is the width of the button. | ||||
| // fHeight is the Height of the button. | ||||
| // fMargin is the space around the button. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateButtonImage(json jRow, string sResRef, string sId, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = ""); | ||||
|  | ||||
| // Creates a basic text box that is not editable element in jRow. | ||||
| // jRow is the row the TextEdit box goes into. | ||||
| // sId is the bind variable so we can change the text. | ||||
| // fWidth the width of the box. | ||||
| // fHeight the height of the box. | ||||
| // bBorder will add border TRUE or remove it FALSE. | ||||
| // nScroll use NUI_SCROLLBARS_* | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateTextBox(json jRow, string sId, float fWidth, float fHeight, int bBorder = TRUE, int nScroll = NUI_SCROLLBARS_AUTO, string sTooltip = ""); | ||||
|  | ||||
| // Creates a basic text edit box element in jRow. | ||||
| // jRow is the row the TextEdit box goes into. | ||||
| // sPlaceHolderBind is the bind for Placeholder. | ||||
| // sValueBind is the bind variable so we can change the text. | ||||
| // nMaxLength is the maximum lenght of the text (1 - 65535) | ||||
| // bMultiline - True or False that is has multiple lines. | ||||
| // fWidth the width of the box. | ||||
| // fHeight the height of the box. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateTextEditBox(json jRow, string sPlaceHolderBind, string sValueBind, int nMaxLength, int bMultiline, float fWidth, float fHeight, string sToolTip = ""); | ||||
|  | ||||
| // Creates a combo box element in jRow. | ||||
| // jRow is the row the combo goes into. | ||||
| // jCombo is the elements/list for the combo box. Use NuiComboEntry to add. | ||||
| // sId is the binds for the combo and the event uses sId + "_event" | ||||
| //      sId + "_selected" is the bind for the selection in the combo box. | ||||
| // fWidth is the width of the combo. | ||||
| // fHeight is the Height of the combo. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateCombo(json jRow, json jCombo, string sId, float fWidth, float fHeight, string sToolTip = ""); | ||||
|  | ||||
| // Creates an image element in jRow. | ||||
| // jRow is the row the Image goes into. | ||||
| // sImage is the resref of the image to use. If "" is passed then it will | ||||
| // create a bind of sId + "_image". | ||||
| // nAspect is the aspect of the image NUI_ASPECT_*. | ||||
| // nHAlign is the horizontal alignment of the image NUI_HALIGN_*. | ||||
| // nVAlign is the vertical alignment of the image NUI_VALIGN_*. | ||||
| // fWidth the width of the box. | ||||
| // fHeight the height of the box. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateImage(json jRow, string sResRef, string sId, int nAspect, int nHAlign, int nVAlign, float fWidth, float fHeight, float fMargin = -1.0, string sToolTip = ""); | ||||
|  | ||||
| // Creates a check box element in jRow. | ||||
| // jRow is the row the Checkbox box goes into. | ||||
| // sLabel is the text placed in the label. | ||||
| //     If "" is passed then it will create a bind of sId + "_label". | ||||
| // sId is the bind variable so we can change the text. | ||||
| //     sId + "_check" is the Bind:bool for if it is checked or not. | ||||
| // fWidth is the width of the label. | ||||
| // fHeight is the Height of the label. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateCheckBox(json jRow, string sLabel, string sId, float fWidth, float fHeight, string sToolTip = ""); | ||||
|  | ||||
| // Creates a slider (Int based) element in jRow | ||||
| // jRow is the row the Check box goes into. | ||||
| // sId is the bind name. | ||||
| // The binds are as follows. | ||||
| // Value: sId + "_value" | ||||
| // Minimum: sId + "_min" | ||||
| // Maximum: sId + "_max" | ||||
| // Step size: sId + "_stepsize" | ||||
| // fWidth is the width of the slider. | ||||
| // fHeight is the Height of the slider. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateSlider(json jRow, string sId, float fWidth, float fHeight, string sToolTip = ""); | ||||
|  | ||||
| // Creates an Options element in jRow. | ||||
| // jRow is the row the Options will start on. | ||||
| // sId is the bind name. | ||||
| // The binds are as follows: | ||||
| //      Value: sId + "_value" | ||||
| //      Event is sId + "_event" | ||||
| // nDirection: NUI_DIRECTION_* | ||||
| // fWidth is the width of the options labels. | ||||
| // fHeight is the height of the options labels. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateOptions(json jRow, string sId, int nDirection, json jLabels, float fWidth, float fHeight, string sToolTip = ""); | ||||
|  | ||||
| // Creates a list element in jRow. | ||||
| // jRow is the row the list will start on. | ||||
| // jElements is the list of elements in the list. Use NuiListTemplateCell to add. | ||||
| // sId is the bind name. | ||||
| // The binds are Event is sId + "_event". | ||||
| // Row count is bound to sId + "_count". | ||||
| // fRowHeight is the height of the rendered rows. | ||||
| // fWidth is the width of the options labels. | ||||
| // fHeight is the height of the options labels. | ||||
| // sTooltip is the tooltip bind value. | ||||
| json CreateList(json jRow, json jElements, string sId, float fRowHeight, float fWidth, float fHeight, string sTooltip = ""); | ||||
|  | ||||
| // Placed here temporarily until we can clean up our includes! | ||||
| void ai_SetDMWAccessButton(int nButton, int bOn = TRUE); | ||||
| int ai_GetDMWAccessButton(int nButton); | ||||
| void ai_SetDMAIAccessButton(int nButton, int bOn = TRUE); | ||||
| int ai_GetDMAIAccessButton(int nButton); | ||||
|  | ||||
| void SaveMenuToCampaignDb(object oPC, int nToken, string sWndId) | ||||
| { | ||||
|     json jGeometry = NuiGetBind(oPC, nToken, "window_geometry"); | ||||
|     float fX = JsonGetFloat(JsonObjectGet(jGeometry, "x")); | ||||
|     float fY = JsonGetFloat(JsonObjectGet(jGeometry, "y")); | ||||
|     string sName = ai_RemoveIllegalCharacters(GetName(oPC)); | ||||
|     json jLocations = ai_GetCampaignDbJson("locations", sName, AI_DM_TABLE); | ||||
|     json jNUI = JsonObjectGet(jLocations, sWndId); | ||||
|     if(JsonGetType(jNUI) == JSON_TYPE_NULL) jNUI = JsonObject(); | ||||
|     jNUI = JsonObjectSet(jNUI, "x", JsonFloat(fX)); | ||||
|     jNUI = JsonObjectSet(jNUI, "y", JsonFloat(fY)); | ||||
|     jLocations = JsonObjectSet(jLocations, sWndId, jNUI); | ||||
|     ai_SetCampaignDbJson("locations", jLocations, sName, AI_DM_TABLE); | ||||
| } | ||||
|  | ||||
| float GetGUIWidthMiddle(object oPC, float fMenuWidth) | ||||
| { | ||||
|     // Get players window information. | ||||
|     float fGUI_Width = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_WIDTH)); | ||||
|     float fGUI_Scale = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0; | ||||
|     fMenuWidth = fMenuWidth * fGUI_Scale; | ||||
|     return (fGUI_Width / 2.0) - (fMenuWidth / 2.0); | ||||
| } | ||||
| float GetGUIHeightMiddle(object oPC, float fMenuHeight) | ||||
| { | ||||
|     // Get players window information. | ||||
|     float fGUI_Height = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_HEIGHT)); | ||||
|     float fGUI_Scale = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0; | ||||
|     fMenuHeight = fMenuHeight * fGUI_Scale; | ||||
|     return (fGUI_Height / 2.0) - (fMenuHeight / 2.0); | ||||
| } | ||||
| int IsWindowClosed(object oPC, string sWndId) | ||||
| { | ||||
|     int nToken = NuiFindWindow(oPC, sWndId); | ||||
|     if(nToken) | ||||
|     { | ||||
|         NuiDestroy(oPC, nToken); | ||||
|         return FALSE; | ||||
|     } | ||||
|     return TRUE; | ||||
| } | ||||
| int SetWindow(object oPC, json jLayout, string sWinID, string sTitle, float fX, float fY, float fWidth, float fHeight, int bResize, int bCollapse, int bClose, int bTransparent, int bBorder, string sEventScript = "") | ||||
| { | ||||
|     json jWindow; | ||||
|     if (bCollapse) jWindow = NuiWindow (jLayout, NuiBind ("window_title"), NuiBind ("window_geometry"), | ||||
|     NuiBind ("window_resizable"), JsonNull (), NuiBind ("window_closable"), | ||||
|     NuiBind ("window_transparent"), NuiBind ("window_border")); | ||||
|  | ||||
|     else jWindow = NuiWindow (jLayout, NuiBind ("window_title"), NuiBind ("window_geometry"), | ||||
|     NuiBind ("window_resizable"), JsonBool (FALSE), NuiBind ("window_closable"), | ||||
|     NuiBind ("window_transparent"), NuiBind ("window_border")); | ||||
|  | ||||
|     int nToken = NuiCreate (oPC, jWindow, sWinID, sEventScript); | ||||
|     if(!bCollapse && !bClose && !bBorder) NuiSetBind (oPC, nToken, "window_title", JsonBool (FALSE)); | ||||
|     else NuiSetBind (oPC, nToken, "window_title", JsonString (sTitle)); | ||||
|     if (fX == -1.0) fX = GetGUIWidthMiddle (oPC, fWidth); | ||||
|     if (fY == -1.0) fY = GetGUIHeightMiddle (oPC, fHeight); | ||||
|     int nScale = GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE); | ||||
|     if(nScale != 100) | ||||
|     { | ||||
|         fHeight = fHeight * (IntToFloat(1050 - nScale) / 1000.0); | ||||
|         fWidth = fWidth * (IntToFloat(1200 - nScale) / 1000.0); | ||||
|     } | ||||
|     NuiSetBind (oPC, nToken, "window_geometry", NuiRect (fX, | ||||
|                 fY, fWidth, fHeight)); | ||||
|     NuiSetBind (oPC, nToken, "window_resizable", JsonBool (bResize)); | ||||
|     NuiSetBind (oPC, nToken, "window_closable", JsonBool (bClose)); | ||||
|     NuiSetBind (oPC, nToken, "window_transparent", JsonBool (bTransparent)); | ||||
|     NuiSetBind (oPC, nToken, "window_border", JsonBool (bBorder)); | ||||
|     return nToken; | ||||
| } | ||||
| json CreateLabel(json jRow, string sLabel, string sId, float fWidth, float fHeight, int nHAlign = 0, int nVAlign = 0, float fMargin = -1.0, string sTooltip = "") | ||||
| { | ||||
|     json jLabel; | ||||
|     if(sLabel == "") jLabel = NuiId(NuiLabel(NuiBind(sId + "_label"), JsonInt(nHAlign), JsonInt(nVAlign)), sId); | ||||
|     else jLabel = NuiId(NuiLabel(JsonString(sLabel), JsonInt(nHAlign), JsonInt(nVAlign)), sId); | ||||
|     jLabel = NuiWidth(jLabel, fWidth); | ||||
|     jLabel = NuiHeight(jLabel, fHeight); | ||||
|     if (fMargin > -1.0) jLabel = NuiMargin(jLabel, fMargin); | ||||
|     if(sTooltip != "") jLabel = NuiTooltip (jLabel, NuiBind (sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jLabel); | ||||
| } | ||||
| json CreateButton(json jRow, string sLabel, string sId, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = "") | ||||
| { | ||||
|     json jButton; | ||||
|     if(sLabel == "") jButton = NuiEnabled(NuiId(NuiButton(NuiBind (sId + "_label")), sId), NuiBind(sId + "_event")); | ||||
|     else jButton = NuiEnabled(NuiId(NuiButton(JsonString(sLabel)), sId), NuiBind(sId + "_event")); | ||||
|     jButton = NuiWidth(jButton, fWidth); | ||||
|     jButton = NuiHeight(jButton, fHeight); | ||||
|     if (fMargin > -1.0) jButton = NuiMargin(jButton, fMargin); | ||||
|     if (sTooltip != "") jButton = NuiTooltip(jButton, NuiBind (sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jButton); | ||||
| } | ||||
| json CreateButtonSelect(json jRow, string sLabel, string sId, float fWidth, float fHeight, string sTooltip = "") | ||||
| { | ||||
|     json jButton; | ||||
|     if(sLabel == "") jButton = NuiEnabled(NuiId(NuiButtonSelect(NuiBind (sId + "_label"), NuiBind(sId)), sId), NuiBind(sId + "_event")); | ||||
|     else jButton = NuiEnabled(NuiId(NuiButtonSelect(JsonString(sLabel), NuiBind(sId)), sId), NuiBind(sId + "_event")); | ||||
|     jButton = NuiWidth(jButton, fWidth); | ||||
|     jButton = NuiHeight(jButton, fHeight); | ||||
|     if(sTooltip != "") jButton = NuiTooltip(jButton, NuiBind (sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jButton); | ||||
| } | ||||
| json CreateButtonImage(json jRow, string sResRef, string sId, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = "") | ||||
| { | ||||
|     json jButton; | ||||
|     if(sResRef == "") jButton = NuiEnabled(NuiId (NuiButtonImage(NuiBind(sId + "_image")), sId), NuiBind(sId + "_event")); | ||||
|     else jButton = NuiEnabled(NuiId(NuiButtonImage(JsonString(sResRef)), sId), NuiBind(sId + "_event")); | ||||
|     jButton = NuiWidth(jButton, fWidth); | ||||
|     jButton = NuiHeight(jButton, fHeight); | ||||
|     if(fMargin > -1.0) jButton = NuiMargin(jButton, fMargin); | ||||
|     if(sTooltip != "") jButton = NuiTooltip(jButton, NuiBind (sTooltip)); | ||||
|     jButton = NuiEncouraged(jButton, NuiBind(sId + "_encouraged")); | ||||
|     return JsonArrayInsert(jRow, jButton); | ||||
| } | ||||
| json CreateTextBox(json jRow, string sId, float fWidth, float fHeight, int bBorder = TRUE, int nScroll = NUI_SCROLLBARS_AUTO, string sTooltip = "") | ||||
| { | ||||
|     json jTextBox = NuiEnabled(NuiText(NuiBind(sId), bBorder, nScroll), NuiBind(sId + "_event")); | ||||
|     jTextBox = NuiWidth(jTextBox, fWidth); | ||||
|     jTextBox = NuiHeight(jTextBox, fHeight); | ||||
|     if(sTooltip != "") jTextBox = NuiTooltip(jTextBox, NuiBind (sTooltip)); | ||||
|     return JsonArrayInsert(jRow, JsonObjectSet(jTextBox, "text_color", NuiColor (255, 0, 0))); | ||||
| } | ||||
| json CreateTextEditBox(json jRow, string sPlaceHolderBind, string sValueBind, int nMaxLength, int bMultiline, float fWidth, float fHeight, string sTooltip = "") | ||||
| { | ||||
|     json jObject = NuiEnabled(NuiTextEdit(NuiBind(sPlaceHolderBind), NuiBind(sValueBind), nMaxLength, bMultiline), NuiBind(sValueBind + "_event")); | ||||
|     jObject = NuiWidth(jObject, fWidth); | ||||
|     jObject = NuiHeight(jObject, fHeight); | ||||
|     if(sTooltip != "") jObject = NuiTooltip(jObject, NuiBind (sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jObject); | ||||
| } | ||||
| json CreateCombo(json jRow, json jList, string sId, float fWidth, float fHeight, string sTooltip = "") | ||||
| { | ||||
|     json jCombo; | ||||
|     if(JsonGetType(jList) == JSON_TYPE_NULL) | ||||
|     { | ||||
|         jCombo = NuiId(NuiCombo(NuiBind(sId + "_list"), NuiBind(sId + "_selected")), sId + "_event"); | ||||
|     } | ||||
|     jCombo = NuiId(NuiCombo(jList, NuiBind (sId + "_selected")), sId); | ||||
|     jCombo = NuiEnabled(jCombo, NuiBind (sId + "_event")); | ||||
|     jCombo = NuiWidth(jCombo, fWidth); | ||||
|     jCombo = NuiHeight(jCombo, fHeight); | ||||
|     if(sTooltip != "") jCombo = NuiTooltip(jCombo, NuiBind(sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jCombo); | ||||
| } | ||||
| json CreateImage(json jRow, string sResRef, string sId, int nAspect, int nHAlign, int nVAlign, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = "") | ||||
| { | ||||
|     json jImage; | ||||
|     if(sResRef == "") jImage = NuiEnabled(NuiId(NuiImage(NuiBind(sId + "_image"), JsonInt(nAspect), JsonInt(nHAlign), JsonInt(nVAlign)), sId), NuiBind(sId + "_event")); | ||||
|     else jImage = NuiEnabled(NuiId(NuiImage(JsonString(sResRef), JsonInt(nAspect), JsonInt(nHAlign), JsonInt(nVAlign)), sId), NuiBind(sId + "_event")); | ||||
|     jImage = NuiWidth(jImage, fWidth); | ||||
|     jImage = NuiHeight(jImage, fHeight); | ||||
|     if (fMargin > -1.0) jImage = NuiMargin(jImage, fMargin); | ||||
|     if(sTooltip != "") jImage = NuiTooltip(jImage, NuiBind(sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jImage); | ||||
| } | ||||
| json CreateCheckBox(json jRow, string sLabel, string sId, float fWidth, float fHeight, string sTooltip = "") | ||||
| { | ||||
|     json jCheckBox; | ||||
|     if(sLabel == "") jCheckBox = NuiEnabled(NuiId(NuiCheck(NuiBind(sId + "_label"), NuiBind(sId + "_check")), sId), NuiBind(sId + "_event")); | ||||
|     else jCheckBox = NuiEnabled(NuiId(NuiCheck(JsonString(sLabel), NuiBind(sId + "_check")), sId), NuiBind(sId + "_event")); | ||||
|     jCheckBox = NuiWidth(jCheckBox, fWidth); | ||||
|     jCheckBox = NuiHeight(jCheckBox, fHeight); | ||||
|     if (sTooltip != "") jCheckBox = NuiTooltip (jCheckBox, NuiBind (sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jCheckBox); | ||||
| } | ||||
| json CreateSlider(json jRow, string sId, float fWidth, float fHeight, string sTooltip = "") | ||||
| { | ||||
|     json jSlider; | ||||
|     jSlider = NuiEnabled(NuiId(NuiSlider(NuiBind(sId + "_value"), NuiBind(sId + "_min"), NuiBind(sId + "_max"), NuiBind(sId + "_stepsize")), sId), NuiBind(sId + "_event")); | ||||
|     jSlider = NuiWidth(jSlider, fWidth); | ||||
|     jSlider = NuiHeight(jSlider, fHeight); | ||||
|     if(sTooltip != "") jSlider = NuiTooltip(jSlider, NuiBind(sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jSlider); | ||||
| } | ||||
| json CreateOptions(json jRow, string sId, int nDirection, json jLabels, float fWidth, float fHeight, string sTooltip = "") | ||||
| { | ||||
|     json jOption; | ||||
|     jOption = NuiEnabled(NuiId(NuiOptions(nDirection, jLabels, NuiBind(sId + "_value")), sId), NuiBind(sId + "_event")); | ||||
|     jOption = NuiWidth(jOption, fWidth); | ||||
|     jOption = NuiHeight(jOption, fHeight); | ||||
|     if(sTooltip != "") jOption = NuiTooltip (jOption, NuiBind (sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jOption); | ||||
| } | ||||
| json CreateList(json jRow, json jElements, string sId, float fRowHeight, float fWidth, float fHeight, string sTooltip = "") | ||||
| { | ||||
|     json jList; | ||||
|     jList = NuiId(NuiList(jElements, NuiBind(sId), fRowHeight), sId + "_id"); | ||||
|     jList = NuiWidth(jList, fWidth); | ||||
|     jList = NuiHeight(jList, fHeight); | ||||
|     if (sTooltip != "") jList = NuiTooltip(jList, NuiBind(sTooltip)); | ||||
|     return JsonArrayInsert(jRow, jList); | ||||
| } | ||||
| void ai_SetDMWAccessButton(int nButton, int bOn = TRUE) | ||||
| { | ||||
|     json jRules = ai_GetCampaignDbJson("rules"); | ||||
|     int nWidgetButtons = JsonGetInt(JsonObjectGet(jRules, sDMWidgetAccessVarname)); | ||||
|     if(bOn) nWidgetButtons = nWidgetButtons | nButton; | ||||
|     else nWidgetButtons = nWidgetButtons & ~nButton; | ||||
|     SetLocalInt(GetModule(), sDMWidgetAccessVarname, nWidgetButtons); | ||||
|     jRules = JsonObjectSet(jRules, sDMWidgetAccessVarname, JsonInt(nWidgetButtons)); | ||||
|     ai_SetCampaignDbJson("rules", jRules); | ||||
| } | ||||
| int ai_GetDMWAccessButton(int nButton) | ||||
| { | ||||
|     int nWidgetButtons = GetLocalInt(GetModule(), sDMWidgetAccessVarname); | ||||
|     return nWidgetButtons & nButton; | ||||
| } | ||||
| void ai_SetDMAIAccessButton(int nButton, int bOn = TRUE) | ||||
| { | ||||
|     json jRules = ai_GetCampaignDbJson("rules"); | ||||
|     int nWidgetButtons = JsonGetInt(JsonObjectGet(jRules, sDMAIAccessVarname)); | ||||
|     if(bOn) nWidgetButtons = nWidgetButtons | nButton; | ||||
|     else nWidgetButtons = nWidgetButtons & ~nButton; | ||||
|     SetLocalInt(GetModule(), sDMAIAccessVarname, nWidgetButtons); | ||||
|     jRules = JsonObjectSet(jRules, sDMAIAccessVarname, JsonInt(nWidgetButtons)); | ||||
|     ai_SetCampaignDbJson("rules", jRules); | ||||
| } | ||||
| int ai_GetDMAIAccessButton(int nButton) | ||||
| { | ||||
|     int nWidgetButtons = GetLocalInt(GetModule(), sDMAIAccessVarname); | ||||
|     return nWidgetButtons & nButton; | ||||
| } | ||||
|  | ||||
							
								
								
									
										793
									
								
								_module/nss/0i_player_target.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										793
									
								
								_module/nss/0i_player_target.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,793 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0i_player_target | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Include script for handling player targeting functions. | ||||
|  | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_associates" | ||||
| #include "0i_menus" | ||||
| // Setup an AI OnPlayerTarget Event script while allowing any module onplayer | ||||
| // target event script to still work. | ||||
| void ai_SetupPlayerTarget(object oCreature); | ||||
| // Selects a target for oAssocite to follow. | ||||
| void ai_AllSelectTarget(object oPC, object oAssociate, object oTarget); | ||||
| // Removes the Cutscene ghosts and variables from all associates. For original AI scripts. | ||||
| void ai_OriginalRemoveAllActionMode(object oPC); | ||||
| // Removes the Cutscene ghosts and Command mode from all associates. | ||||
| void ai_RemoveAllActionMode(object oPC); | ||||
| // Once a trap has been selected from the associates inventory move to placing the trap. | ||||
| void ai_SelectTrap(object oPC, object oAssociate, object oItem); | ||||
| // Place the selected trap at the location selected by the player for OBJECT_SELF. | ||||
| void ai_PlaceTrap(object oPC, location lLocation); | ||||
| // Adds a creature to nGroup for oDM | ||||
| void ai_AddToGroup(object oDM, object oTarget, string sTargetMode); | ||||
| // Has nGroup perform an action based on the selected target or location. | ||||
| void ai_DMAction(object oDM, object oTarget, location lLocation, string sTargetMode); | ||||
| // Get oPC to select a spell target for oAssociate. | ||||
| void ai_SelectWidgetSpellTarget(object oPC, object oAssociate, string sElem); | ||||
| // Updates oAssociates widget by destroying the current one and rebuilding. | ||||
| void ai_UpdateAssociateWidget(object oPC, object oAssociate); | ||||
| // Sets oAssociates action mode for nFeat from the quick widget menu | ||||
| int ai_SetActionMode(object oAssociate, int nFeat); | ||||
|  | ||||
| void ai_SetupPlayerTarget(object oCreature) | ||||
| { | ||||
|     object oModule = GetModule(); | ||||
|     string sModuleTargetEvent = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_TARGET); | ||||
|     if(sModuleTargetEvent != "") | ||||
|     { | ||||
|         if(sModuleTargetEvent != "0e_player_target") SetLocalString(oModule, AI_MODULE_TARGET_EVENT, sModuleTargetEvent); | ||||
|     } | ||||
|     SetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_TARGET, "0e_player_target"); | ||||
| } | ||||
| void ai_OriginalActionAssociate(object oPC, object oTarget, location lLocation) | ||||
| { | ||||
|     object oAssociate = OBJECT_SELF; | ||||
|     if(!GetLocalInt(oAssociate, sGhostModeVarname) && GetLocalInt(oPC, sGhostModeVarname)) | ||||
|     { | ||||
|         effect eGhost = EffectCutsceneGhost(); | ||||
|         ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oAssociate); | ||||
|         SetLocalInt(oAssociate, sGhostModeVarname, TRUE); | ||||
|     } | ||||
|     int nObjectType = GetObjectType(oTarget); | ||||
|     ai_ClearCreatureActions(TRUE); | ||||
|     if(oTarget == GetArea(oPC)) | ||||
|     { | ||||
|         ActionMoveToLocation(lLocation, TRUE); | ||||
|         if(GetLocalObject(oPC, AI_FOLLOW_TARGET) == oAssociate) | ||||
|         { | ||||
|             float fFollowDistance = 3.0; | ||||
|             AssignCommand(oPC, ai_ClearCreatureActions()); | ||||
|             AssignCommand(oPC, ActionForceFollowObject(oAssociate, fFollowDistance)); | ||||
|         } | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_CREATURE) | ||||
|     { | ||||
|         if(oTarget != GetLocalObject(oPC, AI_TARGET_ASSOCIATE)) | ||||
|         { | ||||
|             if(GetMaster(oTarget) == oPC) | ||||
|             { | ||||
|                 SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION"); | ||||
|                 SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oTarget); | ||||
|                 ai_SendMessages(GetName(oTarget) + " is now in Action Mode.", AI_COLOR_YELLOW, oPC); | ||||
|             } | ||||
|             else ActionMoveToObject(oTarget, TRUE); | ||||
|         } | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_DOOR) | ||||
|     { | ||||
|         if(GetIsTrapped(oTarget) && GetAssociateState(NW_ASC_DISARM_TRAPS, oAssociate)) | ||||
|         { | ||||
|             if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate); | ||||
|             if(GetTrapDetectedBy(oTarget, oAssociate)) | ||||
|             { | ||||
|                 bkAttemptToDisarmTrap(oTarget); | ||||
|                 EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         if(GetLocked(oTarget)) bkAttemptToOpenLock(oTarget); | ||||
|         if(GetIsOpen(oTarget)) | ||||
|         { | ||||
|             ActionCloseDoor(oTarget, TRUE); | ||||
|         } | ||||
|         else ActionOpenDoor(oTarget, TRUE); | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_ITEM) | ||||
|     { | ||||
|         ActionPickUpItem(oTarget); | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_PLACEABLE) | ||||
|     { | ||||
|         ActionMoveToObject(oTarget, TRUE); | ||||
|         if(GetHasInventory(oTarget)) | ||||
|         { | ||||
|             if(GetIsTrapped(oTarget) && GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oAssociate)) | ||||
|             { | ||||
|                 if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate); | ||||
|                 if(GetTrapDetectedBy(oTarget, oAssociate)) | ||||
|                 { | ||||
|                     bkAttemptToDisarmTrap(oTarget); | ||||
|                     EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                     return; | ||||
|                 } | ||||
|                 if(GetLocked(oTarget)) | ||||
|                 { | ||||
|                     if(GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oAssociate)) | ||||
|                     { | ||||
|                         bkAttemptToOpenLock(oTarget); | ||||
|                     } | ||||
|                     else AssignCommand(oAssociate, ai_HaveCreatureSpeak(oAssociate, 0, "This " + GetName(oTarget) + " is locked!")); | ||||
|                     EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                     return; | ||||
|                 } | ||||
|                 DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE); | ||||
|             } | ||||
|             else if(GetLocked(oTarget)) | ||||
|             { | ||||
|                 if(GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oAssociate)) | ||||
|                 { | ||||
|                     bkAttemptToOpenLock(oTarget); | ||||
|                 } | ||||
|                 else AssignCommand(oAssociate, ai_HaveCreatureSpeak(oAssociate, 0, "This " + GetName(oTarget) + " is locked!")); | ||||
|                 EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                 return; | ||||
|             } | ||||
|             DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE); | ||||
|         } | ||||
|         DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE); | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_TRIGGER) | ||||
|     { | ||||
|         if(GetIsTrapped(oTarget) && GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oAssociate)) | ||||
|         { | ||||
|             if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate); | ||||
|             if(GetTrapDetectedBy(oTarget, oAssociate)) bkAttemptToDisarmTrap(oTarget); | ||||
|         } | ||||
|     } | ||||
|     EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
| } | ||||
| void ai_OriginalActionAllAssociates(object oPC, object oTarget, location lLocation) | ||||
| { | ||||
|     object oAssociate; | ||||
|     int nIndex; | ||||
|     for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) | ||||
|     { | ||||
|        oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); | ||||
|        if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_OriginalActionAssociate(oPC, oTarget, lLocation)); | ||||
|     } | ||||
|     for(nIndex = 2; nIndex < 6; nIndex++) | ||||
|     { | ||||
|         oAssociate = GetAssociate(nIndex, oPC); | ||||
|         if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_OriginalActionAssociate(oPC, oTarget, lLocation)); | ||||
|     } | ||||
| } | ||||
| void ai_ActionAssociate(object oPC, object oTarget, location lLocation) | ||||
| { | ||||
|     object oAssociate = OBJECT_SELF; | ||||
|     if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) && | ||||
|        !ai_GetAIMode(oAssociate, AI_MODE_GHOST) && | ||||
|        !GetLocalInt(oAssociate, sGhostModeVarname)) | ||||
|     { | ||||
|         effect eGhost = EffectCutsceneGhost(); | ||||
|         ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oAssociate); | ||||
|         SetLocalInt(oAssociate, sGhostModeVarname, TRUE); | ||||
|     } | ||||
|     int nObjectType = GetObjectType(oTarget); | ||||
|     ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, TRUE); | ||||
|     ai_ClearCreatureActions(TRUE); | ||||
|     if(oTarget == GetArea(oPC)) | ||||
|     { | ||||
|         ActionMoveToLocation(lLocation, TRUE); | ||||
|         if(GetLocalObject(oPC, AI_FOLLOW_TARGET) == oAssociate) | ||||
|         { | ||||
|             float fFollowDistance = ai_GetFollowDistance(oPC); | ||||
|             if(GetDistanceBetween(oAssociate, oPC) <= fFollowDistance) | ||||
|             { | ||||
|                 DelayCommand(fFollowDistance, AssignCommand(oPC, ActionMoveToObject(oAssociate, TRUE, fFollowDistance))); | ||||
|             } | ||||
|             else AssignCommand(oPC, ActionMoveToObject(oAssociate, TRUE, fFollowDistance)); | ||||
|         } | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_CREATURE) | ||||
|     { | ||||
|         if(GetIsDead(oTarget)) | ||||
|         { | ||||
|             AssignCommand(oAssociate, ActionDoCommand(ai_SearchObject(oAssociate, oTarget, oPC, TRUE))); | ||||
|         } | ||||
|         else if(GetIsEnemy(oTarget, oAssociate)) | ||||
|         { | ||||
|             // Lock them into attacking this target only. | ||||
|             SetLocalObject(oAssociate, AI_PC_LOCKED_TARGET, oTarget); | ||||
|             // This resets a henchmens failed Moral save in combat. | ||||
|             if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_coward") | ||||
|             { | ||||
|                 SetLocalString(oAssociate, AI_COMBAT_SCRIPT, GetLocalString(oAssociate, AI_DEFAULT_SCRIPT)); | ||||
|             } | ||||
|             if(ai_GetIsInCombat(oAssociate)) ai_DoAssociateCombatRound(oAssociate, oTarget); | ||||
|             else | ||||
|             { | ||||
|                 ai_HaveCreatureSpeak(oAssociate, 5, ":0:1:2:3:6:"); | ||||
|                 ai_StartAssociateCombat(oAssociate, oTarget); | ||||
|             } | ||||
|             ai_SendMessages(GetName(oAssociate) + " is attacking " + GetName(oTarget), AI_COLOR_RED, oPC); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             ActionMoveToObject(oTarget, TRUE); | ||||
|             // Player will be stuck with this variable if they are not using the AI. | ||||
|             DeleteLocalInt(oTarget, "AI_I_AM_BEING_HEALED"); | ||||
|             ActionDoCommand(ai_ActionTryHealing(oAssociate, oTarget)); | ||||
|         } | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_DOOR) | ||||
|     { | ||||
|         if(GetIsTrapped(oTarget)) | ||||
|         { | ||||
|             if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate); | ||||
|             if(GetTrapDetectedBy(oTarget, oAssociate)) | ||||
|             { | ||||
|                 int bStopAction = !GetLocalInt(oTarget, "AI_CANNOT_TRAP_" + GetTag(oAssociate)); | ||||
|                 if(ai_ReactToTrap(oAssociate, oTarget, TRUE)) bStopAction = TRUE; | ||||
|                 if(bStopAction) | ||||
|                 { | ||||
|                     EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if(GetLocked(oTarget)) ai_AttemptToByPassLock(oAssociate, oTarget, TRUE); | ||||
|         else if(GetIsOpen(oTarget)) ActionCloseDoor(oTarget, TRUE); | ||||
|         else ActionOpenDoor(oTarget, TRUE); | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_ITEM) | ||||
|     { | ||||
|         ActionPickUpItem(oTarget); | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_PLACEABLE) | ||||
|     { | ||||
|         ActionMoveToObject(oTarget, TRUE); | ||||
|         if(GetHasInventory(oTarget)) | ||||
|         { | ||||
|             if(GetIsTrapped(oTarget)) | ||||
|             { | ||||
|                 if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate); | ||||
|                 if(GetTrapDetectedBy(oTarget, oAssociate)) | ||||
|                 { | ||||
|                     if(ai_ReactToTrap(oAssociate, oTarget, TRUE)) | ||||
|                     { | ||||
|                         EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|             if(GetLocked(oTarget)) ai_AttemptToByPassLock(oAssociate, oTarget, TRUE); | ||||
|             else ActionDoCommand(ai_SearchObject(oAssociate, oTarget, oPC, TRUE)); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if(ai_GetAIMode(oAssociate, AI_MODE_BASH_LOCKS)) | ||||
|             { | ||||
|                 AssignCommand(oAssociate, ai_ClearCreatureActions()); | ||||
|                 // Check to make sure we are using a melee weapon. | ||||
|                 if(ai_GetIsMeleeWeapon(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oAssociate)) || | ||||
|                    ai_EquipBestMeleeWeapon(oAssociate)) | ||||
|                 { | ||||
|                     AssignCommand(oAssociate, ActionWait(1.0)); | ||||
|                     AssignCommand(oAssociate, ActionAttack(oTarget)); | ||||
|                 } | ||||
|             } | ||||
|             else AssignCommand(oAssociate, DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE)); | ||||
|         } | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_TRIGGER) | ||||
|     { | ||||
|         if(GetIsTrapped(oTarget)) | ||||
|         { | ||||
|             if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate); | ||||
|             if(GetTrapDetectedBy(oTarget, oAssociate)) ai_ReactToTrap(oAssociate, oTarget, TRUE); | ||||
|         } | ||||
|     } | ||||
|     EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
| } | ||||
| void ai_ActionAllAssociates(object oPC, object oTarget, location lLocation) | ||||
| { | ||||
|     object oAssociate; | ||||
|     int nIndex; | ||||
|     for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) | ||||
|     { | ||||
|        oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); | ||||
|        if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation)); | ||||
|     } | ||||
|     for(nIndex = 2; nIndex < 6; nIndex++) | ||||
|     { | ||||
|         oAssociate = GetAssociate(nIndex, oPC); | ||||
|         if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation)); | ||||
|     } | ||||
| } | ||||
| void ai_SelectFollowTarget(object oPC, object oAssociate, object oTarget) | ||||
| { | ||||
|     string sAssociateType = ai_GetAssociateType(oPC, oAssociate); | ||||
|     int nToken = NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI); | ||||
|     float fRange = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE) + | ||||
|                    StringToFloat(Get2DAString("appearance", "PREFATCKDIST", GetAppearanceType(oAssociate))); | ||||
|     string sRange = FloatToString(fRange, 0, 0); | ||||
|     if(oAssociate == oTarget) | ||||
|     { | ||||
|         ai_SetAIMode(oAssociate, AI_MODE_FOLLOW, FALSE); | ||||
|         DeleteLocalObject(oAssociate, AI_FOLLOW_TARGET); | ||||
|         string sTarget; | ||||
|         if(ai_GetIsCharacter(oAssociate)) | ||||
|         { | ||||
|             sTarget = "nobody"; | ||||
|             ai_SendMessages(GetName(oAssociate) + " is not following anyone now!", AI_COLOR_YELLOW, oPC); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             sTarget = GetName(oPC); | ||||
|             ai_SendMessages(GetName(oAssociate) + " is now following " + sTarget + "!", AI_COLOR_YELLOW, oPC); | ||||
|         } | ||||
|         ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_follow_target_tooltip", "  " + GetName(oAssociate) + " following " + sTarget + " [" + sRange + " meters]"); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         ai_SetAIMode(oAssociate, AI_MODE_FOLLOW, TRUE); | ||||
|         SetLocalObject(oAssociate, AI_FOLLOW_TARGET, oTarget); | ||||
|         ai_SendMessages(GetName(oAssociate) + " is now following " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC); | ||||
|         AssignCommand(oAssociate, ActionMoveToObject(oTarget, TRUE, ai_GetFollowDistance(oAssociate))); | ||||
|         ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_follow_target_tooltip", "  " + GetName(oAssociate) + " following " + GetName(oTarget) + " [" + sRange + " meters]"); | ||||
|     } | ||||
|     aiSaveAssociateModesToDb(oPC, oAssociate); | ||||
| } | ||||
| void ai_OriginalRemoveAllActionMode(object oPC) | ||||
| { | ||||
|     if(!ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST)) return; | ||||
|     object oAssociate; | ||||
|     int nIndex; | ||||
|     for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) | ||||
|     { | ||||
|        oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); | ||||
|        if(oAssociate != OBJECT_INVALID && | ||||
|           !ai_GetAIMode(oAssociate, AI_MODE_GHOST) && | ||||
|           GetLocalInt(oAssociate, sGhostModeVarname)) | ||||
|        { | ||||
|             ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); | ||||
|             DeleteLocalInt(oAssociate, sGhostModeVarname); | ||||
|        } | ||||
|     } | ||||
|     for(nIndex = 2; nIndex < 6; nIndex++) | ||||
|     { | ||||
|         oAssociate = GetAssociate(nIndex, oPC); | ||||
|         if(oAssociate != OBJECT_INVALID && | ||||
|            !ai_GetAIMode(oAssociate, AI_MODE_GHOST) && | ||||
|            GetLocalInt(oAssociate, sGhostModeVarname)) | ||||
|         { | ||||
|             ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); | ||||
|             DeleteLocalInt(oAssociate, sGhostModeVarname); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| void ai_RemoveAllActionMode(object oPC) | ||||
| { | ||||
|     object oAssociate; | ||||
|     int nIndex; | ||||
|     for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++) | ||||
|     { | ||||
|         oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex); | ||||
|         if(oAssociate != OBJECT_INVALID) | ||||
|         { | ||||
|             ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, FALSE); | ||||
|             if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) && | ||||
|                !ai_GetAIMode(oAssociate, AI_MODE_GHOST) && | ||||
|                GetLocalInt(oAssociate, sGhostModeVarname)) | ||||
|             { | ||||
|                 ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); | ||||
|                 DeleteLocalInt(oAssociate, sGhostModeVarname); | ||||
|             } | ||||
|             ExecuteScript("nw_ch_ac1", oAssociate); | ||||
|         } | ||||
|     } | ||||
|     for(nIndex = 2; nIndex < 6; nIndex++) | ||||
|     { | ||||
|         oAssociate = GetAssociate(nIndex, oPC); | ||||
|         if(oAssociate != OBJECT_INVALID) | ||||
|         { | ||||
|             ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, FALSE); | ||||
|             if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) && | ||||
|                !ai_GetAIMode(oAssociate, AI_MODE_GHOST) && | ||||
|                GetLocalInt(oAssociate, sGhostModeVarname)) | ||||
|             { | ||||
|                 ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST); | ||||
|                 DeleteLocalInt(oAssociate, sGhostModeVarname); | ||||
|             } | ||||
|             ExecuteScript("nw_ch_ac1", oAssociate); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| void ai_SelectTrap(object oPC, object oAssociate, object oItem) | ||||
| { | ||||
|     if(GetBaseItemType(oItem) != BASE_ITEM_TRAPKIT) | ||||
|     { | ||||
|         ai_SendMessages("A trap kit was not selected.", AI_COLOR_YELLOW, oPC); | ||||
|         return; | ||||
|     } | ||||
|     ai_SendMessages("Now select a location to place the trap.", AI_COLOR_YELLOW, oPC); | ||||
|     SetLocalObject(oAssociate, "AI_TRAP_KIT", oItem); | ||||
|     SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_PLACE_TRAP"); | ||||
|     OpenInventory(oAssociate, oPC); | ||||
|     EnterTargetingMode(oPC, OBJECT_TYPE_TILE, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
| } | ||||
| void ai_PlaceTrap(object oPC, location lLocation) | ||||
| { | ||||
|     object oItem = GetLocalObject(OBJECT_SELF, "AI_TRAP_KIT"); | ||||
|     itemproperty ipTrap = GetFirstItemProperty(oItem); | ||||
|     if(GetItemPropertyType(ipTrap) == ITEM_PROPERTY_TRAP) | ||||
|     { | ||||
|         ActionUseItemAtLocation(oItem, ipTrap, lLocation); | ||||
|     } | ||||
|     else ai_SendMessages("This trap kit does not have a trap property!", AI_COLOR_YELLOW, oPC); | ||||
| } | ||||
| void ai_AddToGroup(object oDM, object oTarget, string sTargetMode) | ||||
| { | ||||
|     string sGroup = GetStringRight(sTargetMode, 1); | ||||
|     if(oDM == oTarget) | ||||
|     { | ||||
|         ai_SendMessages("Group " + sGroup + " has been cleared.", AI_COLOR_YELLOW, oDM); | ||||
|         string sText = "Group " + sGroup; | ||||
|         NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText + " (Left Action/Right Add)")); | ||||
|         NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText + " (Left Action/Right Add)")); | ||||
|         NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_label", JsonString(sText)); | ||||
|         DeleteLocalJson(oDM, "DM_GROUP" + sGroup); | ||||
|         return; | ||||
|     } | ||||
|     string sName = GetName(oTarget); | ||||
|     json jGroup = GetLocalJson(oDM, "DM_GROUP" + sGroup); | ||||
|     if(JsonGetType(jGroup) == JSON_TYPE_NULL) | ||||
|     { | ||||
|         string sText = sName + "'s group"; | ||||
|         NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText + " [Run]")); | ||||
|         NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText + " [Run]")); | ||||
|         NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_label", JsonString(sText)); | ||||
|         jGroup = JsonArrayInsert(JsonArray(), JsonInt(1)); | ||||
|     } | ||||
|     string sUUID = GetObjectUUID(oTarget); | ||||
|     int nIndex = 1; | ||||
|     string sListUUID = JsonGetString(JsonArrayGet(jGroup, nIndex)); | ||||
|     while(sListUUID != "") | ||||
|     { | ||||
|         if(sListUUID == sUUID) | ||||
|         { | ||||
|             ai_SendMessages("This creature is already in the group!", AI_COLOR_RED, oDM); | ||||
|             return; | ||||
|         } | ||||
|         sListUUID = JsonGetString(JsonArrayGet(jGroup, ++nIndex)); | ||||
|     } | ||||
|     jGroup = JsonArrayInsert(jGroup, JsonString(sUUID)); | ||||
|     ai_SendMessages(sName + " has been saved to group" + sGroup, AI_COLOR_YELLOW, oDM); | ||||
|     SetLocalJson(oDM, "DM_GROUP" + sGroup, jGroup); | ||||
|     EnterTargetingMode(oDM, OBJECT_TYPE_CREATURE, MOUSECURSOR_PICKUP, MOUSECURSOR_PICKUP_DOWN); | ||||
| } | ||||
| void ai_MonsterAction(object oDM, object oTarget, location lLocation, int bRun, int nIndex) | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     int nObjectType = GetObjectType(oTarget); | ||||
|     ai_ClearCreatureActions(TRUE); | ||||
|     if(oTarget == GetArea(oDM)) | ||||
|     { | ||||
|         ActionMoveToLocation(lLocation, bRun); | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_CREATURE) | ||||
|     { | ||||
|         if(GetIsDead(oTarget)) return; | ||||
|         else if(GetIsEnemy(oTarget, oCreature)) | ||||
|         { | ||||
|             // Lock them into attacking this target only. | ||||
|             SetLocalObject(oCreature, AI_PC_LOCKED_TARGET, oTarget); | ||||
|             // This resets a creatures failed Moral save in combat. | ||||
|             if(GetLocalString(oCreature, AI_COMBAT_SCRIPT) == "ai_coward") | ||||
|             { | ||||
|                 SetLocalString(oCreature, AI_COMBAT_SCRIPT, GetLocalString(oCreature, AI_DEFAULT_SCRIPT)); | ||||
|             } | ||||
|             if(ai_GetIsInCombat(oCreature)) ai_DoMonsterCombatRound(oCreature); | ||||
|             else | ||||
|             { | ||||
|                 ai_HaveCreatureSpeak(oCreature, 5, ":0:1:2:3:6:"); | ||||
|                 ai_StartMonsterCombat(oCreature); | ||||
|             } | ||||
|             if(nIndex == 1) | ||||
|             { | ||||
|                 ai_SendMessages(GetName(oCreature) + "'s group is attacking " + GetName(oTarget), AI_COLOR_RED, oDM); | ||||
|             } | ||||
|         } | ||||
|         else if(oTarget == oDM) | ||||
|         { | ||||
|             if(GetLocalInt(oCreature, "AI_FOLLOWING_DM")) | ||||
|             { | ||||
|                 ClearAllActions(FALSE, oCreature); | ||||
|                 DeleteLocalInt(oCreature, "AI_FOLLOWING_DM"); | ||||
|                 if(nIndex == 1) | ||||
|                 { | ||||
|                     ai_SendMessages(GetName(oCreature) + "'s group has stopped following you.", AI_COLOR_RED, oDM); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ActionForceFollowObject(oDM, 4.0); | ||||
|                 SetLocalInt(oCreature, "AI_FOLLOWING_DM", TRUE); | ||||
|                 if(nIndex == 1) | ||||
|                 { | ||||
|                     ai_SendMessages(GetName(oCreature) + "'s group is following you.", AI_COLOR_RED, oDM); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             ActionMoveToObject(oTarget, TRUE); | ||||
|             // Player will be stuck with this variable if they are not using the AI. | ||||
|             DeleteLocalInt(oTarget, "AI_I_AM_BEING_HEALED"); | ||||
|             ActionDoCommand(ai_ActionTryHealing(oCreature, oTarget)); | ||||
|             if(nIndex == 1) | ||||
|             { | ||||
|                 ai_SendMessages(GetName(oCreature) + "'s group is moving to and attempting to heal " + GetName(oTarget), AI_COLOR_RED, oDM); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_DOOR) | ||||
|     { | ||||
|         if(GetIsTrapped(oTarget)) | ||||
|         { | ||||
|             if(GetTrapDetectedBy(oTarget, oDM)) SetTrapDetectedBy(oTarget, oCreature); | ||||
|             if(GetTrapDetectedBy(oTarget, oCreature)) | ||||
|             { | ||||
|                 ai_ReactToTrap(oCreature, oTarget, TRUE); | ||||
|                 EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                 return; | ||||
|             } | ||||
|             else if(GetLocked(oTarget)) ai_AttemptToByPassLock(oCreature, oTarget); | ||||
|         } | ||||
|         else if(GetLocked(oTarget)) ai_AttemptToByPassLock(oCreature, oTarget); | ||||
|         else if(GetIsOpen(oTarget)) | ||||
|         { | ||||
|             ActionCloseDoor(oTarget, TRUE); | ||||
|         } | ||||
|         else ActionOpenDoor(oTarget, TRUE); | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_ITEM) | ||||
|     { | ||||
|         ActionPickUpItem(oTarget); | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_PLACEABLE) | ||||
|     { | ||||
|         ActionMoveToObject(oTarget, TRUE); | ||||
|         if(GetHasInventory(oTarget)) | ||||
|         { | ||||
|             if(GetIsTrapped(oTarget)) | ||||
|             { | ||||
|                 if(GetTrapDetectedBy(oTarget, oDM)) SetTrapDetectedBy(oTarget, oCreature); | ||||
|                 if(GetTrapDetectedBy(oTarget, oCreature)) | ||||
|                 { | ||||
|                     ai_ReactToTrap(oCreature, oTarget, TRUE); | ||||
|                     EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                     return; | ||||
|                 } | ||||
|                 if(GetLocked(oTarget)) | ||||
|                 { | ||||
|                     if(!ai_AttemptToByPassLock(oCreature, oTarget)) | ||||
|                     { | ||||
|                         AssignCommand(oCreature, ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oTarget) + " is locked!")); | ||||
|                     } | ||||
|                     EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                     return; | ||||
|                 } | ||||
|                 DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE); | ||||
|             } | ||||
|             else if(GetLocked(oTarget)) | ||||
|             { | ||||
|                 if(ai_AttemptToByPassLock(oCreature, oTarget)) | ||||
|                 { | ||||
|                     AssignCommand(oCreature, ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oTarget) + " is locked!")); | ||||
|                 } | ||||
|                 EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
|                 return; | ||||
|             } | ||||
|             ActionDoCommand(ai_SearchObject(oCreature, oTarget, oDM, TRUE)); | ||||
|         } | ||||
|         DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE); | ||||
|     } | ||||
|     else if(nObjectType == OBJECT_TYPE_TRIGGER) | ||||
|     { | ||||
|         if(GetIsTrapped(oTarget)) | ||||
|         { | ||||
|             if(GetTrapDetectedBy(oTarget, oDM)) SetTrapDetectedBy(oTarget, oCreature); | ||||
|             if(GetTrapDetectedBy(oTarget, oCreature)) ai_ReactToTrap(oCreature, oTarget, TRUE); | ||||
|         } | ||||
|     } | ||||
|     EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK); | ||||
| } | ||||
| void ai_DMAction(object oDM, object oTarget, location lLocation, string sTargetMode) | ||||
| { | ||||
|     string sGroup = GetStringRight(sTargetMode, 1); | ||||
|     json jGroup = GetLocalJson(oDM, "DM_GROUP" + sGroup); | ||||
|     int bRun = JsonGetInt(JsonArrayGet(jGroup, 0)); | ||||
|     int nIndex = 1; | ||||
|     string sUUID = JsonGetString(JsonArrayGet(jGroup, nIndex)); | ||||
|     object oCreature; | ||||
|     while(sUUID != "") | ||||
|     { | ||||
|         oCreature = GetObjectByUUID(sUUID); | ||||
|         AssignCommand(oCreature, ai_MonsterAction(oDM, oTarget, lLocation, bRun, nIndex)); | ||||
|         sUUID = JsonGetString(JsonArrayGet(jGroup, ++nIndex)); | ||||
|     } | ||||
|     if(nIndex == 0) ai_SendMessages("Group" + sGroup + " is empty!", AI_COLOR_RED, oDM); | ||||
| } | ||||
| void ai_SelectWidgetSpellTarget(object oPC, object oAssociate, string sElem) | ||||
| { | ||||
|     int nIndex; | ||||
|     if(GetStringLength(sElem) == 13) nIndex = StringToInt(GetStringRight(sElem, 2)); | ||||
|     else nIndex = StringToInt(GetStringRight(sElem, 1)); | ||||
|     SetLocalInt(oAssociate, "AI_WIDGET_SPELL_INDEX", nIndex); | ||||
|     string sAssociateType = ai_GetAssociateType(oPC, oAssociate); | ||||
|     json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata"); | ||||
|     json jSpells = JsonArrayGet(jAIData, 10); | ||||
|     json jWidget = JsonArrayGet(jSpells, 2); | ||||
|     json jSpell = JsonArrayGet(jWidget, nIndex); | ||||
|     int nSpell = JsonGetInt(JsonArrayGet(jSpell, 0)); | ||||
|     int nClass = JsonGetInt(JsonArrayGet(jSpell, 1)); | ||||
|     if(nClass == -1) // This is an Item. | ||||
|     { | ||||
|         object oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5))); | ||||
|         int nBaseItemType = GetBaseItemType(oItem); | ||||
|         if(Get2DAString("spells", "Range", nSpell) == "P" || // Self | ||||
|            nBaseItemType == BASE_ITEM_ENCHANTED_POTION || | ||||
|            nBaseItemType == BASE_ITEM_POTIONS) | ||||
|         { | ||||
|             int nIprpSubType = JsonGetInt(JsonArrayGet(jSpell, 4)); | ||||
|             itemproperty ipProperty = GetFirstItemProperty(oItem); | ||||
|             while(GetIsItemPropertyValid(ipProperty)) | ||||
|             { | ||||
|                 if(nIprpSubType == GetItemPropertySubType(ipProperty)) break; | ||||
|                 ipProperty = GetNextItemProperty(oItem); | ||||
|             } | ||||
|             if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE)); | ||||
|             AssignCommand(oAssociate, ActionUseItemOnObject(oItem, ipProperty, oAssociate)); | ||||
|             DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); | ||||
|             return; | ||||
|         } | ||||
|         SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_USE_ITEM"); | ||||
|         if(nSpell == SPELL_HEALINGKIT) | ||||
|         { | ||||
|             EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_MAGIC, MOUSECURSOR_NOMAGIC); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|     else // Feats, Spells, Special Abilities. | ||||
|     { | ||||
|         int nFeat = JsonGetInt(JsonArrayGet(jSpell, 5)); | ||||
|         if(nFeat) | ||||
|         { | ||||
|             if(!nSpell || Get2DAString("spells", "Range", nSpell) == "P" || // Self | ||||
|                nFeat == FEAT_SUMMON_FAMILIAR || nFeat == FEAT_ANIMAL_COMPANION || | ||||
|                nFeat == FEAT_TURN_UNDEAD) | ||||
|             { | ||||
|                 if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE)); | ||||
|                 // Adjust the spell used for wild shape and other shape feats. | ||||
|                 if(nFeat == FEAT_WILD_SHAPE) nSpell += 607; | ||||
|                 if(nFeat == FEAT_ELEMENTAL_SHAPE) | ||||
|                 { | ||||
|                     if(nSpell == 397) nSpell == SUBFEAT_ELEMENTAL_SHAPE_FIRE; | ||||
|                     else if(nSpell == 398) nSpell == SUBFEAT_ELEMENTAL_SHAPE_WATER; | ||||
|                     else if(nSpell == 399) nSpell == SUBFEAT_ELEMENTAL_SHAPE_EARTH; | ||||
|                     else if(nSpell == 400) nSpell == SUBFEAT_ELEMENTAL_SHAPE_AIR; | ||||
|                 } | ||||
|                 // Do special targeting for attack feats. | ||||
|                 if(nFeat == FEAT_STUNNING_FIST || nFeat == FEAT_DIRTY_FIGHTING || | ||||
|                    nFeat == FEAT_WHIRLWIND_ATTACK || nFeat == FEAT_QUIVERING_PALM || | ||||
|                    nFeat == FEAT_KNOCKDOWN || nFeat == FEAT_IMPROVED_KNOCKDOWN || | ||||
|                    nFeat == FEAT_SAP || nFeat == FEAT_KI_DAMAGE || | ||||
|                    nFeat == FEAT_DISARM || nFeat == FEAT_IMPROVED_DISARM || | ||||
|                    nFeat == FEAT_SMITE_EVIL || nFeat == FEAT_SMITE_GOOD) | ||||
|                 { | ||||
|                     SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_USE_FEAT"); | ||||
|                     SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate); | ||||
|                     EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_ATTACK, MOUSECURSOR_NOATTACK); | ||||
|                 } | ||||
|                 // Check feat and adjust if it is an action mode feat. | ||||
|                 if(ai_SetActionMode(oAssociate, nFeat)) return; | ||||
|                 AssignCommand(oAssociate, ActionUseFeat(nFeat, oAssociate, nSpell)); | ||||
|                 DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); | ||||
|                 return; | ||||
|             } | ||||
|             SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_USE_FEAT"); | ||||
|         } | ||||
|         else SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_CAST_SPELL"); | ||||
|     } | ||||
|     SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate); | ||||
|     int nObjectType; | ||||
|     string sTarget = Get2DAString("spells", "TargetType", nSpell); | ||||
|     int nTarget = ai_HexStringToInt(sTarget); | ||||
|     //SendMessageToPC(GetFirstPC(), "nTarget: " + IntToString(nTarget)); | ||||
|     if((nTarget & 1) && !(nTarget & 2) &&!(nTarget & 4)) | ||||
|     { | ||||
|         if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE)); | ||||
|         ai_CastWidgetSpell(oPC, oAssociate, oAssociate, GetLocation(oAssociate)); | ||||
|         DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate)); | ||||
|         return; | ||||
|     } | ||||
|     if((nTarget & 1) || (nTarget & 2)) nObjectType += OBJECT_TYPE_CREATURE; | ||||
|     if(nTarget & 4) nObjectType += OBJECT_TYPE_TILE; | ||||
|     if(nTarget & 8) nObjectType += OBJECT_TYPE_ITEM; | ||||
|     if(nTarget & 16) nObjectType += OBJECT_TYPE_DOOR; | ||||
|     if(nTarget & 32) nObjectType += OBJECT_TYPE_PLACEABLE; | ||||
|     if(nTarget & 64) nObjectType += OBJECT_TYPE_TRIGGER; | ||||
|     string sShape = Get2DAString("spells", "TargetShape", nSpell); | ||||
|     int nShape, nSetData; | ||||
|     float fRange; | ||||
|     if(oPC == oAssociate) | ||||
|     { | ||||
|         nSetData = TRUE; | ||||
|         fRange = ai_GetSpellRange(nSpell); | ||||
|         if(fRange == 0.1) fRange = 0.0; | ||||
|     } | ||||
|     if(sShape == "sphere") | ||||
|     { | ||||
|         nShape = SPELL_TARGETING_SHAPE_SPHERE; | ||||
|         nSetData = TRUE; | ||||
|     } | ||||
|     else if(sShape == "rectangle") | ||||
|     { | ||||
|         nShape = SPELL_TARGETING_SHAPE_RECT; | ||||
|         nSetData = TRUE; | ||||
|     } | ||||
|     else if(sShape == "hsphere") | ||||
|     { | ||||
|         nShape = SPELL_TARGETING_SHAPE_HSPHERE; | ||||
|         nSetData = TRUE; | ||||
|     } | ||||
|     else if(sShape == "cone") nShape = SPELL_TARGETING_SHAPE_CONE; | ||||
|     else nShape = SPELL_TARGETING_SHAPE_NONE; | ||||
|     if(nSetData) | ||||
|     { | ||||
|         float fSizeX = StringToFloat(Get2DAString("spells", "TargetSizeX", nSpell)); | ||||
|         float fSizeY = StringToFloat(Get2DAString("spells", "TargetSizeY", nSpell)); | ||||
|         int nFlags = StringToInt(Get2DAString("spells", "TargetFlags", nSpell)); | ||||
|         SetEnterTargetingModeData(oPC, nShape, fSizeX, fSizeY, nFlags, fRange); | ||||
|     } | ||||
|     EnterTargetingMode(oPC, nObjectType, MOUSECURSOR_MAGIC, MOUSECURSOR_NOMAGIC); | ||||
| } | ||||
| void ai_UpdateAssociateWidget(object oPC, object oAssociate) | ||||
| { | ||||
|     int nUIToken = NuiFindWindow(oPC, ai_GetAssociateType(oPC, oAssociate) + AI_WIDGET_NUI); | ||||
|     if(nUIToken) | ||||
|     { | ||||
|         DelayCommand(0.0, NuiDestroy(oPC, nUIToken)); | ||||
|         DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate)); | ||||
|         /* Not sure why I did this? | ||||
|         if(oPC != oAssociate) | ||||
|         { | ||||
|             nUIToken = NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI); | ||||
|             if(nUIToken) | ||||
|             { | ||||
|                 DelayCommand(0.0, NuiDestroy(oPC, nUIToken)); | ||||
|                 DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC)); | ||||
|             } | ||||
|         } */ | ||||
|     } | ||||
| } | ||||
| int ai_SetActionMode(object oAssociate, int nFeat) | ||||
| { | ||||
|     int nMode; | ||||
|     if(nFeat == FEAT_POWER_ATTACK) nMode = ACTION_MODE_POWER_ATTACK; | ||||
|     else if(nFeat == FEAT_RAPID_SHOT) nMode = ACTION_MODE_RAPID_SHOT; | ||||
|     else if(nFeat == FEAT_FLURRY_OF_BLOWS) nMode = ACTION_MODE_FLURRY_OF_BLOWS; | ||||
|     else if(nFeat == FEAT_IMPROVED_POWER_ATTACK) nMode = ACTION_MODE_IMPROVED_POWER_ATTACK; | ||||
|     else if(nFeat == FEAT_EXPERTISE) nMode = ACTION_MODE_EXPERTISE; | ||||
|     else if(nFeat == FEAT_IMPROVED_EXPERTISE) nMode = ACTION_MODE_IMPROVED_EXPERTISE; | ||||
|     else if(nFeat == FEAT_DIRTY_FIGHTING) nMode = ACTION_MODE_DIRTY_FIGHTING; | ||||
|     if(nMode) | ||||
|     { | ||||
|         SetActionMode(oAssociate, nMode, !GetActionMode(oAssociate, nMode)); | ||||
|         return TRUE; | ||||
|     } | ||||
|     return FALSE; | ||||
| } | ||||
							
								
								
									
										2180
									
								
								_module/nss/0i_spells.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2180
									
								
								_module/nss/0i_spells.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										423
									
								
								_module/nss/0i_states_cond.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								_module/nss/0i_states_cond.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,423 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0i_states_cond | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  Include scripts that handle states and conditions for combat. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_main" | ||||
| #include "0i_messages" | ||||
| #include "0i_time" | ||||
| //#include "X0_I0_COMBAT" | ||||
| // Wrapper for ClearAllActions - we have added extra vars to be cleared as well. | ||||
| // Note this references OBJECT_SELF! | ||||
| void ai_ClearCreatureActions(int bClearCombatState = FALSE); | ||||
| // Used in combat to keep track of the creatures last rounds action. | ||||
| // One use is to make sure we don't use the same spell on the next round. | ||||
| // 0+ is the spell that was cast, other actions use AI_LAST_ACTION_* constants. | ||||
| void ai_SetLastAction(object oCreature, int nAction = AI_LAST_ACTION_NONE); | ||||
| // Returns TRUE if oCreatures last rounds action is equal to nAction. | ||||
| // 0+ is the spell that was cast, other actions use AI_LAST_ACTION_* constants. | ||||
| int ai_CompareLastAction(object oCreature, int nAction); | ||||
| // Sets the correct listen checks on oCreature. | ||||
| void ai_SetListeningPatterns(object oCreature); | ||||
| // Returns TRUE if oCreature is an elemental, undead, or golem i.e. non-living. | ||||
| int ai_IsNonliving(int nRacialType); | ||||
| // Returns TRUE if oCreature is in combat. | ||||
| int ai_GetIsInCombat(object oCreature); | ||||
| // Sets the time that this oCreature's current combat round started. | ||||
| // Using action based combat rounds has an unfortunate side effect: | ||||
| // Once you attack in melee you will continue to attack in melee do to hardcoded | ||||
| // logic. This will "PUSH" your end of round back until it decides to stop attacking! | ||||
| // We avoid this by setting the time and if we check for combat and 6 seconds has | ||||
| // passed then we assume the current round is over, ClearAllActions, and start the next round. | ||||
| void ai_SetCombatRound(object oCreature); | ||||
| // Clears the current combat round timer by deleting the value. | ||||
| void ai_EndCombatRound(object oCreature); | ||||
| // Returns TRUE if AI_COMBAT_ROUND_IN_SECONDS has not passed since ai_SetCombatRound. | ||||
| // If it returns FALSE then it will clear the current combat round timer. | ||||
| int ai_IsInCombatRound(object oCreature, int nCombatRound = AI_COMBAT_ROUND_IN_SECONDS); | ||||
| // Returns TRUE if oCreature is busy. | ||||
| // This checks various actions to see if oCreature is busy; | ||||
| // in combat, busy mode, Actions: attacking, casting spell, counterspelling, | ||||
| // disabling trap, item casting spell, opening lock, resting, setting trap. | ||||
| int ai_GetIsBusy(object oCreature); | ||||
| // Returns a value based on the disabling effect. | ||||
| // Dead = 1, Bleeding = 2, Dying = 2, Stunned = 29, Confused = 24, Paralyzed = 27 | ||||
| // Frightened 25, Turned = 35, Petrified = 79, Charmed = 23, Disappearappear = 75, | ||||
| // Time Stop = 66, Dazed = 28, Sleep = 30. | ||||
| // Returns FALSE if not Disabled. | ||||
| int ai_Disabled(object oCreature); | ||||
| // Set one of the AI_MODE_* bitwise constants on oAssociate to bOn. | ||||
| void ai_SetAIMode(object oAssociate, int nBit, int bOn = TRUE); | ||||
| // Return if nMode is set on oAssociate. Uses the AI_MODE_* bitwise constants. | ||||
| int ai_GetAIMode(object oAssociate, int nBit); | ||||
| // Set one of the AI_MAGIC_* bitwise constants on oAssociate to bOn. | ||||
| void ai_SetMagicMode(object oAssociate, int nBit, int bOn = TRUE); | ||||
| // Return if nMode is set on oAssociate. Uses the AI_MAGIC_* bitwise constants. | ||||
| int ai_GetMagicMode(object oAssociate, int nBit); | ||||
| // This is based off of the PC's settings for an associate and other creatures use a default. | ||||
| // Set one of the AI_LOOT_* bitwise constants on oAssociate to bOn. | ||||
| void ai_SetLootFilter(object oAssociate, int nBit, int bOn = TRUE); | ||||
| // Return if nMode is set on oAssociate. Uses the AI_LOOT_* bitwise constants. | ||||
| int ai_GetLootFilter(object oAssociate, int nBit); | ||||
| // Set one of the AI_IP_* bitwise constants on oCreature to bOn. | ||||
| void ai_SetItemProperty(object oCreature, string sVarname, int nBit, int bOn = TRUE); | ||||
| // Return if nMode is set on oCreature. Uses the AI_IP_* bitwise constants. | ||||
| int ai_GetItemProperty(object oCreature, string sVarname, int nBit); | ||||
| // Returns the number of hitpoints a creature must have to not be healed. | ||||
| // This is based off of the PC's settings for an associate and other creatures use a default. | ||||
| int ai_GetHealersHpLimit(object oCreature, int bInCombat = TRUE); | ||||
| // Returns TRUE if nCondition is within nCurrentConditions. | ||||
| // nCurrentConditions is setup in ai_GetNegativeConditions. | ||||
| int ai_GetHasNegativeCondition(int nCondition, int nCurrentConditions); | ||||
| // Returns an integer with bitwise flags set that represent the current negative | ||||
| // conditions on oCreature. ai_GetHasNegativeCondition uses this function. | ||||
| int ai_GetNegativeConditions(object oCreature); | ||||
| // Returns TRUE if oObject is in the line of sight of oCreature. | ||||
| // If the creature is close LineOfSight doesn't work well. | ||||
| int ai_GetIsInLineOfSight(object oCreature, object oObject); | ||||
| // Add the specified condition flag to the behavior state of the caller | ||||
| void ai_SetBehaviorState(int nCondition, int bValid = TRUE); | ||||
| // Returns TRUE if the specified behavior flag is set on the caller | ||||
| int ai_GetBehaviorState(int nCondition); | ||||
| // Highlights the current mode for the widget passed. | ||||
| void ai_HighlightWidgetMode(object oPC, object oAssociate, int nToken); | ||||
| // Checks to see if the party scale is correctly adjusted. | ||||
| void ai_CheckXPPartyScale(object oCreature); | ||||
|  | ||||
| void ai_ClearCreatureActions(int bClearCombatState = FALSE) | ||||
| { | ||||
|     if(AI_DEBUG) ai_Debug("0i_states_cond", "89", GetName(OBJECT_SELF) + " is clearing actions (" + | ||||
|              IntToString(bClearCombatState) + ")!"); | ||||
|     DeleteLocalInt(OBJECT_SELF, AI_CURRENT_ACTION_MODE); | ||||
|     ClearAllActions(bClearCombatState); | ||||
| } | ||||
| void ai_SetLastAction(object oCreature, int nAction = AI_LAST_ACTION_NONE) | ||||
| { | ||||
|     SetLocalInt(oCreature, sLastActionVarname, nAction); | ||||
| } | ||||
| int ai_CompareLastAction(object oCreature, int nAction) | ||||
| { | ||||
|     // Are we checking to see if we cast a spell? | ||||
|     if(nAction == AI_LAST_ACTION_CAST_SPELL && | ||||
|         GetLocalInt(oCreature, sLastActionVarname) > -1) return TRUE; | ||||
|     // Check other last actions. | ||||
|     return (nAction == GetLocalInt(oCreature, sLastActionVarname)); | ||||
| } | ||||
| void ai_SetListeningPatterns(object oCreature) | ||||
| { | ||||
|     SetListenPattern(oCreature, AI_I_SEE_AN_ENEMY, AI_ALLY_SEES_AN_ENEMY); | ||||
|     SetListenPattern(oCreature, AI_I_HEARD_AN_ENEMY, AI_ALLY_HEARD_AN_ENEMY); | ||||
|     SetListenPattern(oCreature, AI_ATKED_BY_WEAPON, AI_ALLY_ATKED_BY_WEAPON); | ||||
|     SetListenPattern(oCreature, AI_ATKED_BY_SPELL, AI_ALLY_ATKED_BY_SPELL); | ||||
|     SetListenPattern(oCreature, AI_I_AM_WOUNDED, AI_ALLY_IS_WOUNDED); | ||||
|     SetListenPattern(oCreature, AI_I_AM_DEAD, AI_ALLY_IS_DEAD); | ||||
|     SetListenPattern(oCreature, AI_I_AM_DISEASED, AI_ALLY_IS_DISEASED); | ||||
|     SetListenPattern(oCreature, AI_I_AM_POISONED, AI_ALLY_IS_POISONED); | ||||
|     SetListenPattern(oCreature, AI_I_AM_WEAK, AI_ALLY_IS_WEAK); | ||||
|     SetListening(oCreature, TRUE); | ||||
| } | ||||
| int ai_IsNonliving(int nRacialType) | ||||
| { | ||||
|     switch(nRacialType) | ||||
|     { | ||||
|         case RACIAL_TYPE_CONSTRUCT: | ||||
|         case RACIAL_TYPE_ELEMENTAL: | ||||
|         case RACIAL_TYPE_UNDEAD: return TRUE; | ||||
|    } | ||||
|    return FALSE; | ||||
| } | ||||
| int ai_GetIsInCombat(object oCreature) | ||||
| { | ||||
|     if(AI_DEBUG) ai_Debug("0i_states_cond", "110", GetName(oCreature) + " is in Combat: Enemy Numbers = " + IntToString(GetLocalInt(oCreature, AI_ENEMY_NUMBERS))); | ||||
|  | ||||
|     return GetLocalInt(oCreature, AI_ENEMY_NUMBERS); | ||||
| } | ||||
| void ai_SetCombatRound(object oCreature) | ||||
| { | ||||
|     SetLocalInt(oCreature, "AI_COMBAT_ROUND_START", SQLite_GetTimeStamp()); | ||||
|     if(AI_DEBUG) ai_Debug("0i_states_cond", "116", " ===============> " + GetName(oCreature) + " ROUND START:" + IntToString(SQLite_GetTimeStamp()) + " <==============="); | ||||
| } | ||||
| void ai_EndCombatRound(object oCreature) | ||||
| { | ||||
|     if(AI_DEBUG) ai_Debug("0i_states_cond", "120", " ===============> " + GetName(oCreature) + " ROUND END:" + IntToString(SQLite_GetTimeStamp()) + " <==============="); | ||||
|     DeleteLocalInt(oCreature, "AI_COMBAT_ROUND_START"); | ||||
| } | ||||
| int ai_IsInCombatRound(object oCreature, int nCombatRound = AI_COMBAT_ROUND_IN_SECONDS) | ||||
| { | ||||
|     int nCombatRoundStart = GetLocalInt(oCreature, "AI_COMBAT_ROUND_START"); | ||||
|     if(AI_DEBUG) ai_Debug("0i_states_cond", "148", " nCombatRoundStart: " + IntToString(nCombatRoundStart)); | ||||
|     if(!nCombatRoundStart) return FALSE; | ||||
|     // New combat round calculator. If 6 seconds has passed then we are on a new round! | ||||
|     int nSQLTime = SQLite_GetTimeStamp(); | ||||
|     int nCombatRoundTime = nSQLTime - nCombatRoundStart; | ||||
|     if(AI_DEBUG) ai_Debug("0i_states_cond", "153", " SQLite_GetTimeStamp: " + IntToString(nSQLTime) + | ||||
|              "(" + IntToString(nSQLTime - nCombatRoundStart) + ")"); | ||||
|     if(nCombatRoundTime < nCombatRound) return TRUE; | ||||
|     ai_EndCombatRound(oCreature); | ||||
|     return FALSE; | ||||
| } | ||||
| // Testing to see if we can fix some delaying in combat. | ||||
| int ai_GetIsBusy(object oCreature) | ||||
| { | ||||
|     int nAction = GetCurrentAction(oCreature); | ||||
|     if(AI_DEBUG) ai_Debug("0i_states_cond", "140", GetName(oCreature) + " Get is Busy, action: " + | ||||
|              IntToString(nAction)); | ||||
|     switch(nAction) | ||||
|     { | ||||
|         case ACTION_CASTSPELL : | ||||
|         case ACTION_ITEMCASTSPELL : | ||||
|         case ACTION_OPENLOCK : | ||||
|         case ACTION_REST : | ||||
|         case ACTION_DISABLETRAP : | ||||
|         case ACTION_ATTACKOBJECT : | ||||
|         case ACTION_COUNTERSPELL : | ||||
|         case ACTION_SETTRAP : return TRUE; | ||||
|         case ACTION_WAIT : | ||||
|         case ACTION_INVALID : | ||||
|         { | ||||
|             int nCombatWait = GetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); | ||||
|             if(AI_DEBUG) ai_Debug("0i_states_cond", "153", "nCombatWait: " + IntToString(nCombatWait) + | ||||
|                      " AI_AM_I_SEARCHING: " + IntToString(GetLocalInt(oCreature, AI_AM_I_SEARCHING))); | ||||
|             if(nCombatWait) | ||||
|             { | ||||
|                 if(ai_IsInCombatRound(oCreature, nCombatWait)) return TRUE; | ||||
|                 DeleteLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS); | ||||
|             } | ||||
|             else if(GetLocalInt(oCreature, AI_AM_I_SEARCHING)) DeleteLocalInt(oCreature, AI_AM_I_SEARCHING); | ||||
|             return FALSE; | ||||
|         } | ||||
|         case ACTION_MOVETOPOINT : | ||||
|         { | ||||
|             return ai_GetIsInCombat(oCreature); | ||||
|         } | ||||
|     } | ||||
|     return FALSE; | ||||
| } | ||||
| int ai_Disabled(object oCreature) | ||||
| { | ||||
|     if(GetIsDead(oCreature)) return 1; | ||||
|     // Check for effects. | ||||
|     effect eEffect = GetFirstEffect(oCreature); | ||||
|     while(GetIsEffectValid(eEffect)) | ||||
|     { | ||||
|         switch(GetEffectType(eEffect)) | ||||
|         { | ||||
|             case EFFECT_TYPE_DOMINATED : | ||||
|             { | ||||
|                 if(!GetCommandable(oCreature)) SetCommandable(TRUE, oCreature); | ||||
|                 return FALSE; | ||||
|             } | ||||
|             case EFFECT_TYPE_STUNNED : | ||||
|             case EFFECT_TYPE_DAZED : | ||||
|             case EFFECT_TYPE_SLEEP : | ||||
|             case EFFECT_TYPE_CONFUSED : | ||||
|             case EFFECT_TYPE_FRIGHTENED : | ||||
|             case EFFECT_TYPE_PARALYZE : | ||||
|             case EFFECT_TYPE_TURNED : | ||||
|             case EFFECT_TYPE_CHARMED : | ||||
|             case EFFECT_TYPE_PETRIFY : | ||||
|             case EFFECT_TYPE_TIMESTOP : | ||||
|             { | ||||
|                 if(AI_DEBUG) ai_Debug("0i_stats_cond", "195", GetName(oCreature) + " is disabled(" + | ||||
|                          IntToString(GetEffectType(eEffect)) + ")"); | ||||
|                 return GetEffectType(eEffect); | ||||
|             } | ||||
|         } | ||||
|         eEffect = GetNextEffect(oCreature); | ||||
|     } | ||||
|     // Not Commandable is basically disabled as far as the AI is concerned. | ||||
|     if(!GetCommandable(oCreature)) | ||||
|     { | ||||
|         if(AI_DEBUG) ai_Debug("0i_stats_cond", "213", GetName(oCreature) + " is disabled(Not Commandable)!"); | ||||
|         return EFFECT_TYPE_PARALYZE; | ||||
|     } | ||||
|     if(AI_DEBUG) ai_Debug("0i_states_cond", "202", GetName(oCreature) + " is not disabled."); | ||||
|     return FALSE; | ||||
| } | ||||
| void ai_SetAIMode(object oAssociate, int nBit, int bOn = TRUE) | ||||
| { | ||||
|     int nAIModes = GetLocalInt(oAssociate, sAIModeVarname); | ||||
|     if(bOn) nAIModes = nAIModes | nBit; | ||||
|     else nAIModes = nAIModes & ~nBit; | ||||
|     SetLocalInt(oAssociate, sAIModeVarname, nAIModes); | ||||
|     // Set widget to show the mode they are in. | ||||
|  | ||||
| } | ||||
| int ai_GetAIMode(object oAssociate, int nBit) | ||||
| { | ||||
|     if(GetLocalInt(oAssociate, sAIModeVarname) & nBit) return TRUE; | ||||
|     return FALSE; | ||||
| } | ||||
| void ai_SetMagicMode(object oAssociate, int nBit, int bOn = TRUE) | ||||
| { | ||||
|     int nMagicModes = GetLocalInt(oAssociate, sMagicModeVarname); | ||||
|     if(bOn) nMagicModes = nMagicModes | nBit; | ||||
|     else nMagicModes = nMagicModes & ~nBit; | ||||
|     SetLocalInt(oAssociate, sMagicModeVarname, nMagicModes); | ||||
| } | ||||
| int ai_GetMagicMode(object oAssociate, int nBit) | ||||
| { | ||||
|     if(GetLocalInt(oAssociate, sMagicModeVarname) & nBit) return TRUE; | ||||
|     return FALSE; | ||||
| } | ||||
| void ai_SetLootFilter(object oAssociate, int nLootBit, int bOn = TRUE) | ||||
| { | ||||
|     int nLootFilter = GetLocalInt(oAssociate, sLootFilterVarname); | ||||
|     if(bOn) nLootFilter = nLootFilter | nLootBit; | ||||
|     else nLootFilter = nLootFilter & ~nLootBit; | ||||
|     SetLocalInt(oAssociate, sLootFilterVarname, nLootFilter); | ||||
| } | ||||
| int ai_GetLootFilter(object oAssociate, int nBit) | ||||
| { | ||||
|     if(GetLocalInt(oAssociate, sLootFilterVarname) & nBit) return TRUE; | ||||
|     return FALSE; | ||||
| } | ||||
| void ai_SetItemProperty(object oCreature, string sVarname, int nBit, int bOn = TRUE) | ||||
| { | ||||
|     int nItemProperties = GetLocalInt(oCreature, sVarname); | ||||
|     if(bOn) nItemProperties = nItemProperties | nBit; | ||||
|     else nItemProperties = nItemProperties & ~nBit; | ||||
|     SetLocalInt(oCreature, sVarname, nItemProperties); | ||||
| } | ||||
| int ai_GetItemProperty(object oCreature, string sVarname, int nBit) | ||||
| { | ||||
|     if(GetLocalInt(oCreature, sVarname) & nBit) return TRUE; | ||||
|     return FALSE; | ||||
| } | ||||
| int ai_GetHealersHpLimit(object oCreature, int bInCombat = TRUE) | ||||
| { | ||||
|     if(bInCombat) return GetLocalInt(oCreature, AI_HEAL_IN_COMBAT_LIMIT); | ||||
|     else return GetLocalInt(oCreature, AI_HEAL_OUT_OF_COMBAT_LIMIT); | ||||
| } | ||||
| int ai_GetHasNegativeCondition(int nCondition, int nCurrentConditions) | ||||
| { | ||||
|     return (nCurrentConditions & nCondition); | ||||
| } | ||||
| int ai_GetNegativeConditions(object oCreature) | ||||
| { | ||||
|     int nCondition, nEffectType; | ||||
|     effect eEffect = GetFirstEffect(oCreature); | ||||
|     while(GetIsEffectValid (eEffect)) | ||||
|     { | ||||
|         // Rage and maybe other abilities might come from the oCreature! | ||||
|         if(GetEffectCreator(eEffect) != oCreature) | ||||
|         { | ||||
|             nEffectType = GetEffectType(eEffect); | ||||
|             switch(nEffectType) | ||||
|             { | ||||
|                 case EFFECT_TYPE_DISEASE:          nCondition = nCondition | AI_CONDITION_DISEASE; break; | ||||
|                 case EFFECT_TYPE_POISON:           nCondition = nCondition | AI_CONDITION_POISON; break; | ||||
|                 case EFFECT_TYPE_CURSE:            nCondition = nCondition | AI_CONDITION_CURSE; break; | ||||
|                 case EFFECT_TYPE_BLINDNESS: | ||||
|                 case EFFECT_TYPE_DEAF:             nCondition = nCondition | AI_CONDITION_BLINDDEAF; break; | ||||
|                 case EFFECT_TYPE_ABILITY_DECREASE: nCondition = nCondition | AI_CONDITION_ABILITY_DRAIN; break; | ||||
|                 case EFFECT_TYPE_NEGATIVELEVEL:    nCondition = nCondition | AI_CONDITION_LEVEL_DRAIN; break; | ||||
|                 case EFFECT_TYPE_AC_DECREASE:      nCondition = nCondition | AI_CONDITION_AC_DECREASE; break; | ||||
|                 case EFFECT_TYPE_ATTACK_DECREASE:  nCondition = nCondition | AI_CONDITION_ATK_DECREASE; break; | ||||
|                 case EFFECT_TYPE_CHARMED:          nCondition = nCondition | AI_CONDITION_CHARMED; break; | ||||
|                 case EFFECT_TYPE_CONFUSED:         nCondition = nCondition | AI_CONDITION_CONFUSED; break; | ||||
|                 case EFFECT_TYPE_DAZED:            nCondition = nCondition | AI_CONDITION_DAZED; break; | ||||
|                 case EFFECT_TYPE_DAMAGE_DECREASE:  nCondition = nCondition | AI_CONDITION_DMG_DECREASE; break; | ||||
|                 case EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE: nCondition = nCondition | AI_CONDITION_DMG_I_DECREASE; break; | ||||
|                 case EFFECT_TYPE_DOMINATED:        nCondition = nCondition | AI_CONDITION_DOMINATED; break; | ||||
|                 case EFFECT_TYPE_FRIGHTENED:       nCondition = nCondition | AI_CONDITION_FRIGHTENED; break; | ||||
|                 case EFFECT_TYPE_PARALYZE:         nCondition = nCondition | AI_CONDITION_PARALYZE; break; | ||||
|                 case EFFECT_TYPE_SAVING_THROW_DECREASE: nCondition = nCondition | AI_CONDITION_SAVE_DECREASE; break; | ||||
|                 case EFFECT_TYPE_SKILL_DECREASE:   nCondition = nCondition | AI_CONDITION_SKILL_DECREASE; break; | ||||
|                 case EFFECT_TYPE_SLOW:             nCondition = nCondition | AI_CONDITION_SLOW; break; | ||||
|                 case EFFECT_TYPE_SPELL_RESISTANCE_DECREASE: nCondition = nCondition | AI_CONDITION_SR_DECREASE; break; | ||||
|                 case EFFECT_TYPE_STUNNED:          nCondition = nCondition | AI_CONDITION_STUNNED; break; | ||||
|             } | ||||
|         } | ||||
|         eEffect = GetNextEffect(oCreature); | ||||
|     } | ||||
|     return nCondition; | ||||
| } | ||||
| int ai_GetIsInLineOfSight(object oCreature, object oObject) | ||||
| { | ||||
|     // Creatures can block the line of sight so when close we shouldn't check. | ||||
|     if(GetDistanceBetween(oObject, oCreature) <= AI_RANGE_MELEE) return TRUE; | ||||
|     return LineOfSightObject(oCreature, oObject); | ||||
| } | ||||
| void ai_SetBehaviorState(int nCondition, int bValid = TRUE) | ||||
| { | ||||
|     int nPlot = GetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER"); | ||||
|     if(bValid) | ||||
|     { | ||||
|         nPlot = nPlot | nCondition; | ||||
|         SetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER", nPlot); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         nPlot = nPlot & ~nCondition; | ||||
|         SetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER", nPlot); | ||||
|     } | ||||
| } | ||||
| int ai_GetBehaviorState(int nCondition) | ||||
| { | ||||
|     int nPlot = GetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER"); | ||||
|     if(nPlot & nCondition) return TRUE; | ||||
|     return FALSE; | ||||
| } | ||||
| void ai_HighlightWidgetMode(object oPC, object oAssociate, int nToken) | ||||
| { | ||||
|     if(oPC == oAssociate) return; | ||||
|     int bBool; | ||||
|     bBool = ai_GetAIMode(oAssociate,AI_MODE_DEFEND_MASTER); | ||||
|     NuiSetBind(oPC, nToken, "btn_cmd_guard_encouraged", JsonBool(bBool)); | ||||
|     bBool = ai_GetAIMode(oAssociate,AI_MODE_STAND_GROUND); | ||||
|     NuiSetBind(oPC, nToken, "btn_cmd_hold_encouraged", JsonBool(bBool)); | ||||
|     bBool = ai_GetAIMode(oAssociate,AI_MODE_FOLLOW); | ||||
|     NuiSetBind(oPC, nToken, "btn_cmd_follow_encouraged", JsonBool(bBool)); | ||||
|     if(!ai_GetAIMode(oAssociate, AI_MODE_DEFEND_MASTER) && | ||||
|        !ai_GetAIMode(oAssociate, AI_MODE_STAND_GROUND) && | ||||
|        !ai_GetAIMode(oAssociate, AI_MODE_FOLLOW)) bBool = TRUE; | ||||
|     else bBool = FALSE; | ||||
|     NuiSetBind(oPC, nToken, "btn_cmd_attack_encouraged", JsonBool(bBool)); | ||||
| } | ||||
| void ai_CheckXPPartyScale(object oCreature) | ||||
| { | ||||
|     object oModule = GetModule(); | ||||
|     if(!GetLocalInt(oModule, AI_RULE_PARTY_SCALE)) return; | ||||
|     object oMaster; | ||||
|     if(!ai_GetIsCharacter(oCreature)) | ||||
|     { | ||||
|         oMaster = GetMaster(oCreature); | ||||
|         while(oMaster != OBJECT_INVALID) | ||||
|         { | ||||
|             if(ai_GetIsCharacter(oMaster)) break; | ||||
|             oMaster = GetMaster(oMaster); | ||||
|         } | ||||
|         if(oMaster == OBJECT_INVALID) return; | ||||
|     } | ||||
|     else oMaster = oCreature; | ||||
|     float fDefaultXPScale = IntToFloat(GetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP)); | ||||
|     float fPartySize = 4.0; | ||||
|     int nAssociateType, nHenchman, nHenchAssociate; | ||||
|     object oHenchman; | ||||
|     for(nAssociateType = 1; nAssociateType <= 5; nAssociateType++) | ||||
|     { | ||||
|         if(nAssociateType == ASSOCIATE_TYPE_HENCHMAN) | ||||
|         { | ||||
|             for(nHenchman = 1; nHenchman <= AI_MAX_HENCHMAN; nHenchman++) | ||||
|             { | ||||
|                 oHenchman = GetAssociate(nAssociateType, oMaster, nHenchman); | ||||
|                 if(oHenchman != OBJECT_INVALID) | ||||
|                 { | ||||
|                     fPartySize += 1.0; | ||||
|                     for(nHenchAssociate = 2; nHenchAssociate <= 5; nHenchAssociate++) | ||||
|                     { | ||||
|                         if(GetAssociate(nHenchAssociate, oHenchman, 1) != OBJECT_INVALID) fPartySize += 1.0; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else if(GetAssociate(nAssociateType, oMaster, 1) != OBJECT_INVALID) fPartySize += 1.0; | ||||
|     } | ||||
|     int nXPScale = FloatToInt(fPartySize / 4.0 * fDefaultXPScale); | ||||
|     //SendMessageToPC(oMaster, GetName(oMaster) + " nXPScale = (3 + fPartySize / 4.0 * fDefaultXPScale)" + | ||||
|     //                IntToString(nXPScale) + " = (" + FloatToString(fPartySize, 0, 1) + " / 4.0 * " + | ||||
|     //                FloatToString(fDefaultXPScale, 0, 1) + ")"); | ||||
|     SetModuleXPScale(nXPScale); | ||||
| } | ||||
|  | ||||
							
								
								
									
										3100
									
								
								_module/nss/0i_talents.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3100
									
								
								_module/nss/0i_talents.nss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										95
									
								
								_module/nss/0i_time.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								_module/nss/0i_time.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0i_time | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Include script for handling all time functions for the server. | ||||
|  | ||||
|  Lokey's functions: | ||||
| int GetPosixTimestamp(); | ||||
| string GetCurrentDateTime(); | ||||
|  | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| // RETURNS a Timestamp in seconds since 1970-01-01. | ||||
| int GetCurrentTimeInSeconds(); | ||||
| // RETURNS a formated date, good for timestamping logs and text. | ||||
| string GetCurrentDateTime(); | ||||
| // Sends a server shutdown message 1800 seconds i.e 30 minutes before. | ||||
| // nDuration is in seconds. i.e. one hours is 3600 defaults to 24 hours (86400). | ||||
| // Should be put into the servers OnHeartBeat. | ||||
| void CheckServerShutdownMessage(int nDuration = 86400); | ||||
|  | ||||
| int GetCurrentTimeInSeconds() | ||||
| { | ||||
|     string stmt = "SELECT strftime('%s','now');"; | ||||
|     sqlquery sqlQuery = SqlPrepareQueryObject(GetModule(), stmt); | ||||
|     SqlStep(sqlQuery); | ||||
|     return SqlGetInt(sqlQuery, 0); | ||||
| } | ||||
| string GetCurrentDateTime() | ||||
| { | ||||
|     string stmt = "SELECT datetime('now', 'localtime')"; | ||||
|     sqlquery sqlQuery = SqlPrepareQueryObject(GetModule(), stmt); | ||||
|     SqlStep(sqlQuery); | ||||
|     return SqlGetString(sqlQuery, 0); | ||||
| } | ||||
| /// @addtogroup time Time | ||||
| /// @brief Provides various time related functions. | ||||
| /// @brief Returns the current time formatted according to the provided sqlite date time format string. | ||||
| /// @param format Format string as used by sqlites STRFTIME(). | ||||
| /// @return The current time in the requested format. Empty string on error. | ||||
| string SQLite_GetFormattedSystemTime(string format); | ||||
| /// @return Returns the number of seconds since midnight on January 1, 1970. | ||||
| int SQLite_GetTimeStamp(); | ||||
| /// @return Returns the number of milliseconds since midnight on January 1, 1970. | ||||
| int SQLite_GetTimeMilliseconds(); | ||||
| /// @brief A millisecond timestamp | ||||
| struct SQLite_MillisecondTimeStamp | ||||
| { | ||||
|     int seconds; ///< Seconds since epoch | ||||
|     int milliseconds; ///< Milliseconds | ||||
| }; | ||||
| /// @remark For mircosecond timestamps use NWNX_Utility_GetHighResTimeStamp(). | ||||
| /// @return Returns the number of milliseconds since midnight on January 1, 1970. | ||||
| struct SQLite_MillisecondTimeStamp SQLite_GetMillisecondTimeStamp(); | ||||
| /// @brief Returns the current date. | ||||
| /// @return The date in the format (mm/dd/yyyy). | ||||
| string SQLite_GetSystemDate(); | ||||
| /// @brief Returns current time. | ||||
| /// @return The current time in the format (24:mm:ss). | ||||
| string SQLite_GetSystemTime(); | ||||
| /// @} | ||||
| string SQLite_GetFormattedSystemTime(string format) | ||||
| { | ||||
|     sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME(@format, 'now', 'localtime')"); | ||||
|     SqlBindString(query, "@format", format); | ||||
|     SqlStep(query); // sqlite returns NULL for invalid format in STRFTIME() | ||||
|     return SqlGetString(query, 0); | ||||
| } | ||||
| int SQLite_GetTimeStamp() | ||||
| { | ||||
|     sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME('%s', 'now')"); | ||||
|     SqlStep(query); | ||||
|     return SqlGetInt(query, 0); | ||||
| } | ||||
| int SQLite_GetTimeMillisecond() | ||||
| { | ||||
|     sqlquery query = SqlPrepareQueryObject(GetModule(), "select cast((julianday('now') - 2440587.5) * 86400 * 1000 as integer)"); | ||||
|     SqlStep(query); | ||||
|     return SqlGetInt(query, 0); | ||||
| } | ||||
| struct SQLite_MillisecondTimeStamp SQLite_GetMillisecondTimeStamp() | ||||
| { | ||||
|     sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME('%s', 'now'), SUBSTR(STRFTIME('%f', 'now'), 4)"); | ||||
|     SqlStep(query); | ||||
|     struct SQLite_MillisecondTimeStamp t; | ||||
|     t.seconds = SqlGetInt(query, 0); | ||||
|     t.milliseconds = SqlGetInt(query, 1); | ||||
|     return t; | ||||
| } | ||||
| string SQLite_GetSystemDate() | ||||
| { | ||||
|     return SQLite_GetFormattedSystemTime("%m/%d/%Y"); | ||||
| } | ||||
| string SQLite_GetSystemTime() | ||||
| { | ||||
|     return SQLite_GetFormattedSystemTime("%H:%M:%S"); | ||||
| } | ||||
							
								
								
									
										105
									
								
								_module/nss/ai_a_ambusher.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								_module/nss/ai_a_ambusher.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_ambusher | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates to ambush creatures by hiding or turning invisible. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
|  * This assumes we are not invisible since the ai_a_invisible script should fire if we are. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_ambusher", "19", GetName(oCreature) + " is using ambusher tactics: " + | ||||
|              " oNearestEnemy: " + GetName(oNearestEnemy) + " fDistance: " + | ||||
|              FloatToString(GetDistanceBetween(oNearestEnemy, oCreature), 0, 2)); | ||||
|     if(GetDistanceBetween(oNearestEnemy, oCreature) > AI_RANGE_CLOSE) | ||||
|     { | ||||
|         // Has our master told us to not use magic? | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC)) | ||||
|         { | ||||
|             // If can turn invisible then we should probably do that! | ||||
|             if(ai_UseTalent(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature)) return; | ||||
|             if(ai_UseTalent(oCreature, SPELL_INVISIBILITY, oCreature)) return; | ||||
|             if(ai_UseTalent(oCreature, SPELL_INVISIBILITY_SPHERE, oCreature)) return; | ||||
|             if(ai_UseTalent(oCreature, SPELL_SANCTUARY, oCreature)) return; | ||||
|             if(ai_UseTalent(oCreature, SPELL_ETHEREALNESS, oCreature)) return; // Greater Sanctuary | ||||
|             if(ai_UseTalent(oCreature, SPELLABILITY_AS_IMPROVED_INVISIBLITY, oCreature)) return; | ||||
|             if(ai_UseTalent(oCreature, SPELLABILITY_AS_INVISIBILITY, oCreature)) return; | ||||
|         } | ||||
|     } | ||||
|     // Check the battle field to see if anyone see us? | ||||
|     int nEnemyIndex = ai_GetNearestIndexThatSeesUs(oCreature); | ||||
|     // If seen, can we try to hide now? | ||||
|     if(nEnemyIndex) | ||||
|     { | ||||
|         // Check for an attacker and can they see through invisibility? | ||||
|         object oAttacker = ai_GetEnemyAttackingMe(oCreature); | ||||
|         int bCanSeeInvisible; | ||||
|         if(oAttacker != OBJECT_INVALID) | ||||
|         { | ||||
|             bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_SEEINVISIBLE); | ||||
|             if(!bCanSeeInvisible) bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_TRUESEEING); | ||||
|             if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_5_FEET, oCreature); | ||||
|             if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_10_FEET, oCreature); | ||||
|             if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_60_FEET, oCreature); | ||||
|         } | ||||
|         if(!bCanSeeInvisible) | ||||
|         { | ||||
|             if(GetHasFeat(FEAT_HIDE_IN_PLAIN_SIGHT, oCreature)) | ||||
|             { | ||||
|                 if(!GetActionMode(oCreature, ACTION_MODE_STEALTH)) | ||||
|                 { | ||||
|                     if(AI_DEBUG) ai_Debug("ai_a_ambusher", "55", GetName(oCreature) + " is using hide in plain sight!"); | ||||
|                     ClearAllActions(TRUE); | ||||
|                     SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             // Does not have hide in plain sight. | ||||
|             else | ||||
|             { | ||||
|                 string sEnemyIndex = IntToString(nEnemyIndex); | ||||
|                 float fEnemyDistance = GetLocalFloat(oCreature, AI_ENEMY_RANGE + sEnemyIndex); | ||||
|                 if(AI_DEBUG) ai_Debug("ai_a_ambusher", "66", "fDistance: " + FloatToString(fEnemyDistance, 0, 2)); | ||||
|                 if(fEnemyDistance > 20.0) | ||||
|                 { | ||||
|                     int bTried = GetLocalInt(oCreature, AI_TRIED_TO_HIDE); | ||||
|                     if(!bTried) | ||||
|                     { | ||||
|                         // Move away so we can hide. | ||||
|                         if(AI_DEBUG) ai_Debug("ai_a_ambusher", "73", GetName(oCreature) + " is trying to move away to hide!"); | ||||
|                         SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); | ||||
|                         object oEnemy = GetLocalObject(oCreature, AI_ENEMY + sEnemyIndex); | ||||
|                         ActionMoveAwayFromObject(oEnemy, TRUE, AI_RANGE_BATTLEFIELD); | ||||
|                         SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3); | ||||
|                         return; | ||||
|                     } | ||||
|                     else SetLocalInt(oCreature, AI_TRIED_TO_HIDE, GetLocalInt(oCreature, AI_TRIED_TO_HIDE) - 1); | ||||
|                 } | ||||
|                 // We have been seen by an enemy near us so drop stealth. | ||||
|                 else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); | ||||
|             } | ||||
|         } | ||||
|         // The enemy can see through stealth so lets drop it. | ||||
|         else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); | ||||
|     } | ||||
|     // We are not in stealth mode so and no one sees us so lets hide. | ||||
|     else if(!GetActionMode(oCreature, ACTION_MODE_STEALTH)) | ||||
|     { | ||||
|         // Use any hiding talents we have | ||||
|         if(AI_DEBUG) ai_Debug("ai_a_ambusher", "97", GetName(oCreature) + " is trying to hide!"); | ||||
|         SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); | ||||
|         SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3); | ||||
|         return; | ||||
|     } | ||||
|     // If we have givin up on stealth do our normal actions. | ||||
|     string sScript = GetLocalString(oCreature, AI_DEFAULT_SCRIPT); | ||||
|     if(sScript == "ai_a_ambusher" || sScript == "") sScript = "ai_a_default"; | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_ambusher", "101", "Executing Script: " + sScript); | ||||
|     ExecuteScript(sScript, oCreature); | ||||
| } | ||||
							
								
								
									
										159
									
								
								_module/nss/ai_a_atk_casters.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								_module/nss/ai_a_atk_casters.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_atk_casters | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates to the nearest casting creatures. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
|  Our actions. | ||||
|  1 - Get nearest enemy. | ||||
|  2 - Check for healing and curing first. | ||||
|  3 - Check moral if wounded and this is a simple+ battle. | ||||
|  4 - Check for a magical ranged attack if not in melee and a difficult+ battle. | ||||
|  5 - Check for a buff or summons if this is a difficult+ battle. | ||||
|  6 - Check for a Class ability and an offensive spell if this is a simple+ battle. | ||||
|  7 - Check for a physical attack. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         // ******************* OFFENSIVE AOE TALENTS *********************** | ||||
|         // Check the battlefield for a group of enemies to shoot a big spell at! | ||||
|         // We are checking here since these opportunities are rare and we need | ||||
|         // to take advantage of them as often as possible. | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) | ||||
|         { | ||||
|             // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ | ||||
|             // Does our master want to be buffed first? | ||||
|             object oTarget = OBJECT_INVALID; | ||||
|             if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature); | ||||
|             if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return; | ||||
|             if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; | ||||
|             if(ai_TryDivineMightFeat(oCreature, nInMelee)) return; | ||||
|         } | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     int bAlwaysAtk = !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK); | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_atk_casters", "80", "Check for ranged attack on nearest casting enemy!"); | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) && | ||||
|        !ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && | ||||
|        ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return; | ||||
|             // Lets pick off the nearest targets first. | ||||
|             if(!nInMelee) | ||||
|             { | ||||
|                 if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE); | ||||
|                 if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, AI_RANGE_MELEE); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!"); | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_atk_casters", "119", "Check for melee attack on nearest enemy!"); | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TryWhirlwindFeat(oCreature)) return; | ||||
|     if(ai_TrySneakAttack(oCreature, nInMelee, bAlwaysAtk)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_PERCEPTION, bAlwaysAtk); | ||||
|     if(oTarget == OBJECT_INVALID) | ||||
|     { | ||||
|         object oPCTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET); | ||||
|         if(oPCTarget == OBJECT_INVALID) | ||||
|         { | ||||
|             // Are we in melee? If so try to get the nearest enemy in melee. | ||||
|             if(nInMelee > 0) | ||||
|             { | ||||
|                 oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk); | ||||
|                 // If we didn't get a target then get any target within range. | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk); | ||||
|             } | ||||
|             // If not then lets go find someone to attack! | ||||
|             else | ||||
|             { | ||||
|                 // Get the nearest enemy. | ||||
|                 oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk); | ||||
|                 // If we didn't get a target then get any target within range. | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     // We might not have a target this is fine as sometimes we don't want to attack! | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_atk_casters", "149", GetName(oTarget) + " is the nearest target for melee combat!"); | ||||
|     // If we don't find a target then we don't want to fight anyone! | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         if(AI_DEBUG) ai_Debug("ai_a_atk_casters", "154", "Do melee attack against (caster/nearest): " + GetName(oTarget) + "!"); | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
| } | ||||
|  | ||||
							
								
								
									
										80
									
								
								_module/nss/ai_a_atk_nearest.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								_module/nss/ai_a_atk_nearest.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_atk_nearest | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates to the nearest target. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
|  Our actions. | ||||
|  1 - Get nearest enemy. | ||||
|  2 - Check for healing and curing first. | ||||
|  3 - Check moral if wounded and this is a simple+ battle. | ||||
|  4 - Check for a magical ranged attack if not in melee and a difficult+ battle. | ||||
|  5 - Check for a buff or summons if this is a difficult+ battle. | ||||
|  6 - Check for a Class ability and an offensive spell if this is a simple+ battle. | ||||
|  7 - Check for a physical attack. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         // ******************* OFFENSIVE AOE TALENTS *********************** | ||||
|         // Check the battlefield for a group of enemies to shoot a big spell at! | ||||
|         // We are checking here since these opportunities are rare and we need | ||||
|         // to take advantage of them as often as possible. | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) | ||||
|         { | ||||
|             // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ | ||||
|             // Does our master want to be buffed first? | ||||
|             object oTarget = OBJECT_INVALID; | ||||
|             if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature); | ||||
|             if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return; | ||||
|             if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; | ||||
|             if(ai_TryDivineMightFeat(oCreature, nInMelee)) return; | ||||
|         } | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     ai_DoPhysicalAttackOnNearest(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
| } | ||||
|  | ||||
							
								
								
									
										159
									
								
								_module/nss/ai_a_atk_warrior.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								_module/nss/ai_a_atk_warrior.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_atk_warrior | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates to the nearest casting creatures. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
|  Our actions. | ||||
|  1 - Get nearest enemy. | ||||
|  2 - Check for healing and curing first. | ||||
|  3 - Check moral if wounded and this is a simple+ battle. | ||||
|  4 - Check for a magical ranged attack if not in melee and a difficult+ battle. | ||||
|  5 - Check for a buff or summons if this is a difficult+ battle. | ||||
|  6 - Check for a Class ability and an offensive spell if this is a simple+ battle. | ||||
|  7 - Check for a physical attack. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         // ******************* OFFENSIVE AOE TALENTS *********************** | ||||
|         // Check the battlefield for a group of enemies to shoot a big spell at! | ||||
|         // We are checking here since these opportunities are rare and we need | ||||
|         // to take advantage of them as often as possible. | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) | ||||
|         { | ||||
|             // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ | ||||
|             // Does our master want to be buffed first? | ||||
|             object oTarget = OBJECT_INVALID; | ||||
|             if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature); | ||||
|             if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return; | ||||
|             if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; | ||||
|             if(ai_TryDivineMightFeat(oCreature, nInMelee)) return; | ||||
|         } | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     int bAlwaysAtk = !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK); | ||||
|     if(AI_DEBUG) ai_Debug("0i_actions", "496", "Check for ranged attack on nearest casting enemy!"); | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) && | ||||
|        !ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && | ||||
|        ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return; | ||||
|             // Lets pick off the nearest targets first. | ||||
|             if(!nInMelee) | ||||
|             { | ||||
|                 if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE); | ||||
|                 if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR, AI_RANGE_MELEE); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!"); | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_atk_warrior", "119", "Check for melee attack on nearest enemy!"); | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TryWhirlwindFeat(oCreature)) return; | ||||
|     if(ai_TrySneakAttack(oCreature, nInMelee, bAlwaysAtk)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_PERCEPTION, bAlwaysAtk); | ||||
|     if(oTarget == OBJECT_INVALID) | ||||
|     { | ||||
|         object oPCTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET); | ||||
|         if(oPCTarget == OBJECT_INVALID) | ||||
|         { | ||||
|             // Are we in melee? If so try to get the nearest enemy in melee. | ||||
|             if(nInMelee > 0) | ||||
|             { | ||||
|                 oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk); | ||||
|                 // If we didn't get a target then get any target within range. | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk); | ||||
|             } | ||||
|             // If not then lets go find someone to attack! | ||||
|             else | ||||
|             { | ||||
|                 // Get the nearest enemy. | ||||
|                 oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk); | ||||
|                 // If we didn't get a target then get any target within range. | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     // We might not have a target this is fine as sometimes we don't want to attack! | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_atk_warrior", "149", GetName(oTarget) + " is the nearest target for melee combat!"); | ||||
|     // If we don't find a target then we don't want to fight anyone! | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         if(AI_DEBUG) ai_Debug("ai_a_atk_warrior", "154", "Do melee attack against (caster/nearest): " + GetName(oTarget) + "!"); | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
| } | ||||
|  | ||||
							
								
								
									
										87
									
								
								_module/nss/ai_a_barbarian.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								_module/nss/ai_a_barbarian.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_barbarian | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Barbarian class. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     object oTarget; | ||||
|     if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature)) | ||||
|     { | ||||
|         //*************************  HEALING & CURES  ************************** | ||||
|         if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|         if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|         int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|         int nMaxLevel; | ||||
|         // Check for moral and get the maximum spell level we should use. | ||||
|         if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|         { | ||||
|             if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|             nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|         } | ||||
|         // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|         if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|         { | ||||
|             // ************************ CLASS FEATURES ************************* | ||||
|             if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|             // ************************* SPELL TALENTS ************************* | ||||
|             if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|         // Offensive single target talents. | ||||
|         if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|         { | ||||
|             // ************************* SPELL TALENTS ************************* | ||||
|             if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|             { | ||||
|                 if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|                 if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|             } | ||||
|         } | ||||
|         // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|         // ************************ Ranged feat attacks ************************ | ||||
|         if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|         { | ||||
|             if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|             { | ||||
|                 // Are we suppose to protect our master first? | ||||
|                 if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) | ||||
|                 { | ||||
|                     // Lets pick off the weakest targets. | ||||
|                     if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                     else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|                 } | ||||
|                 if(oTarget != OBJECT_INVALID) | ||||
|                 { | ||||
|                     if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                     ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                     return; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|         } | ||||
|     } | ||||
|     // *************************** Melee feat attacks ************************** | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TryWhirlwindFeat(oCreature)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										83
									
								
								_module/nss/ai_a_bard.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								_module/nss/ai_a_bard.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_bard | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Bard class. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget = OBJECT_INVALID; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Are we suppose to protect our master first? | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 // Lets pick off the weakest targets. | ||||
|                 if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TrySneakAttack(oCreature, nInMelee)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										102
									
								
								_module/nss/ai_a_cleric.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								_module/nss/ai_a_cleric.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_cleric | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Cleric class. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         // Turning is basically a powerful AOE so treat it like one. | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         // ******************* OFFENSIVE AOE TALENTS *********************** | ||||
|         // Check the battlefield for a group of enemies to shoot a big spell at! | ||||
|         // We are checking here since these opportunities are rare and we need | ||||
|         // to take advantage of them as often as possible. | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) | ||||
|         { | ||||
|             // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ | ||||
|             // Does our master want to be buffed first? | ||||
|             object oTarget = OBJECT_INVALID; | ||||
|             if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature); | ||||
|             if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return; | ||||
|             if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; | ||||
|             if(ai_TryDivineMightFeat(oCreature, nInMelee)) return; | ||||
|         } | ||||
|     } | ||||
|     // SIMPLE+ - Offensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget = OBJECT_INVALID; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Are we suppose to protect our master first? | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 // Lets pick off the weakest targets. | ||||
|                 if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										69
									
								
								_module/nss/ai_a_cntrspell.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								_module/nss/ai_a_cntrspell.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_cntrspell | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures using the combat mode counter spell. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     // We are not in melee combat then we don't attack. | ||||
|     int bAttack = nInMelee; | ||||
|     if(!bAttack) | ||||
|     { | ||||
|         // If there are no casters, i.e. CLERIC or MAGES in the battle then attack. | ||||
|         struct stClasses stClasses = ai_GetFactionsClasses(oCreature); | ||||
|         if(!stClasses.CLERICS && !stClasses.MAGES) bAttack = TRUE; | ||||
|     } | ||||
|     // If we are not attacking and using magic then setup for counter spelling. | ||||
|     if(!bAttack && !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC)) | ||||
|     { | ||||
|         //***************************  HEALING & CURES  **************************** | ||||
|         if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|         if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|         int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|         if(AI_DEBUG) ai_Debug("ai_a_cntrspell", "30", " Counterspell Mode? " + | ||||
|                  IntToString(GetActionMode(OBJECT_SELF, ACTION_MODE_COUNTERSPELL))); | ||||
|         if(!GetActionMode(oCreature, ACTION_MODE_COUNTERSPELL)) | ||||
|         { | ||||
|             object oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER); | ||||
|             // We can only counter spells from a hasted caster if we are hasted as well. | ||||
|             if(ai_GetHasEffectType(oTarget, EFFECT_TYPE_HASTE) && | ||||
|               !ai_GetHasEffectType(oCreature, EFFECT_TYPE_HASTE)) | ||||
|             { | ||||
|                 // If we have haste then we should cast it. | ||||
|                 if(GetHasSpell(SPELL_HASTE, oCreature)) | ||||
|                 { | ||||
|                     if(AI_DEBUG) ai_Debug("ai_a_cntrspell", "42", "Opponent is hasted! Casting Haste."); | ||||
|                     ActionCastSpellAtObject(SPELL_HASTE, oCreature); | ||||
|                     ai_SetLastAction(oCreature, SPELL_HASTE); | ||||
|                     return; | ||||
|                 } | ||||
|                 // If not then we need to go into normal combat. | ||||
|                 else | ||||
|                 { | ||||
|                     if(AI_DEBUG) ai_Debug("ai_cntrspell", "50", "Opponent is hasted! Using ranged AI."); | ||||
|                     ExecuteScript("ai_a_ranged"); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 // First a good tactic for counter spelling is to be invisible. | ||||
|                 if(ai_TryToBecomeInvisible(oCreature)) return; | ||||
|                 // If we have attempted to become invisible or are invisible then | ||||
|                 // it is time to counter spell. | ||||
|                 if(AI_DEBUG) ai_Debug("ai_a_cntrspell", "61", "Setting Counterspell mode!"); | ||||
|                 ActionCounterSpell(oTarget); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_cntrspell", "67", "Situation is not good for counterspelling! Using ranged AI."); | ||||
|     ExecuteScript("ai_a_ranged"); | ||||
| } | ||||
							
								
								
									
										84
									
								
								_module/nss/ai_a_default.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								_module/nss/ai_a_default.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_no_modes | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates to not use any combat modes during combat ai. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
|  Our actions. | ||||
|  1 - Get nearest enemy. | ||||
|  2 - Check for healing and curing first. | ||||
|  3 - Check moral if wounded and this is a simple+ battle. | ||||
|  4 - Check for a magical ranged attack if not in melee and a difficult+ battle. | ||||
|  5 - Check for a buff or summons if this is a difficult+ battle. | ||||
|  6 - Check for a Class ability and an offensive spell if this is a simple+ battle. | ||||
|  7 - Check for a physical attack. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         // ******************* OFFENSIVE AOE TALENTS *********************** | ||||
|         // Check the battlefield for a group of enemies to shoot a big spell at! | ||||
|         // We are checking here since these opportunities are rare and we need | ||||
|         // to take advantage of them as often as possible. | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) | ||||
|         { | ||||
|             // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ | ||||
|             // Does our master want to be buffed first? | ||||
|             object oTarget = OBJECT_INVALID; | ||||
|             if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature); | ||||
|             if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return; | ||||
|             if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; | ||||
|             if(ai_TryDivineMightFeat(oCreature, nInMelee)) return; | ||||
|         } | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryPolymorphSelfFeat(oCreature)) return; | ||||
|         if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     ai_DoPhysicalAttackOnBest(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
| } | ||||
|  | ||||
							
								
								
									
										77
									
								
								_module/nss/ai_a_defensive.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								_module/nss/ai_a_defensive.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_defensive | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates put in to a defensive mode to protect themselves. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
|  Our actions. | ||||
|  1 - Get nearest enemy and the difficulty of the battle. | ||||
|  2 - Check for healing potions if this is a simple+ battle. | ||||
|  3 - Check moral if wounded and is a simple+ battle. | ||||
|  4 - Check for a magical ranged attack if not in melee and a difficult+ battle. | ||||
|  5 - Check for a buff if this is a difficult+ battle. | ||||
|  6 - Check for defensive ability such as knockdown, expertise or parry. | ||||
|  7 - If we can't fight defensive then flee. | ||||
|  8 - If we are out of range with no ability then stand and watch. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_defensive", "25", "oNearest Enemy: " + GetName(oNearestEnemy) + | ||||
|                  " Distance to Nearest Enemy: " + FloatToString(GetDistanceToObject(oNearestEnemy), 0, 2)); | ||||
|     // ALWAYS - Check for healing and cure talents. | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // SIMPLE+ - Check for moral and get what spell power we should be using. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // DIFFICULT+ - Class talents, Offensive AOE's, Defensive talents, and Potion talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) | ||||
|         { | ||||
|             // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS **************** | ||||
|             // Does our master want to be buffed first? | ||||
|             object oTarget = OBJECT_INVALID; | ||||
|             if (ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature); | ||||
|             int nRound = ai_GetCurrentRound(oCreature); | ||||
|             if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound, oTarget)) return; | ||||
|         } | ||||
|     } | ||||
|     object oTarget; | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     if(nInMelee > 0) | ||||
|     { | ||||
|         if(ai_TryImprovedExpertiseFeat(oCreature)) return; | ||||
|         if(ai_TryExpertiseFeat(oCreature)) return; | ||||
|         // Lets get the strongest melee opponent in melee with us. | ||||
|         oTarget = ai_GetHighestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|         if(oTarget == OBJECT_INVALID) oTarget = oNearestEnemy; | ||||
|         // Use knockdown when appropriate and the target is not immune. | ||||
|         if(ai_TryKnockdownFeat(oCreature, oTarget)) return; | ||||
|         if (ai_TryParry (oCreature)) return; | ||||
|         // We have tried everything to protect ourselves so the only thing left | ||||
|         // to do is man up and attack! | ||||
|         ai_DoPhysicalAttackOnLowestCR(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|         return; | ||||
|     } | ||||
|     //**********************  PHYSICAL ATTACKS  ******************************** | ||||
|     // Even in defensive mode we want to be in battle so go find someone! | ||||
|     ai_DoPhysicalAttackOnBest(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
| } | ||||
							
								
								
									
										86
									
								
								_module/nss/ai_a_druid.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								_module/nss/ai_a_druid.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_druid | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Druid class. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE && ai_TryPolymorphSelfFeat(oCreature)) return; | ||||
|     //**************************  SKILL FEATURES  ************************** | ||||
|     if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     object oTarget; | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Are we suppose to protect our master first? | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 // Lets pick off the weakest targets. | ||||
|                 if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										82
									
								
								_module/nss/ai_a_fighter.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								_module/nss/ai_a_fighter.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: 0i_a_fighter | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Fighter class. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget = OBJECT_INVALID; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Are we suppose to protect our master first? | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 // Lets pick off the weakest targets. | ||||
|                 if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TryWhirlwindFeat(oCreature)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										117
									
								
								_module/nss/ai_a_flanker.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								_module/nss/ai_a_flanker.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_flanker | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates to flank the enemy and not charge into combat. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     oTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET); | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     // Lets get the nearest target that is attacking someone besides me. We want to flank! | ||||
|     if(oTarget == OBJECT_INVALID) | ||||
|     { | ||||
|         if(!nInMelee) oTarget = ai_GetFlankTarget(oCreature); | ||||
|         // If there are few enemies then we can safely move around. | ||||
|         else if(nInMelee < 3 || ai_CanIMoveInCombat(oCreature)) | ||||
|         { | ||||
|             oTarget = ai_GetFlankTarget(oCreature, AI_RANGE_MELEE); | ||||
|         } | ||||
|         // Ok we are in a serious fight so lets not give attack of opportunities. | ||||
|         else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); | ||||
|     } | ||||
|     // If there are no enemies being attacked then lets stay back. | ||||
|     if(oTarget == OBJECT_INVALID) | ||||
|     { | ||||
|         if(nInMelee) | ||||
|         { | ||||
|             if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|             // Lets get the strongest melee opponent in melee with us. | ||||
|             object oTarget = ai_GetHighestCRTargetForMeleeCombat(oCreature, nInMelee); | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         // ************************** Ranged feat attacks ************************** | ||||
|         else if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|         { | ||||
|             if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|             { | ||||
|                 if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return; | ||||
|                 oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 if(oTarget != OBJECT_INVALID) | ||||
|                 { | ||||
|                     if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                     ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|         return; | ||||
|     } | ||||
|     // Are we too far from our master? | ||||
|     object oMaster = GetMaster(); | ||||
|     if(GetDistanceBetween(oMaster, oCreature) > AI_RANGE_LONG) | ||||
|     { | ||||
|         ActionMoveToObject(oMaster, TRUE, AI_RANGE_CLOSE); | ||||
|         return; | ||||
|     } | ||||
|     ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE); | ||||
| } | ||||
							
								
								
									
										123
									
								
								_module/nss/ai_a_invisible.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								_module/nss/ai_a_invisible.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_invisible | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates to use when they are invisible. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     // Has our master told us to not use magic? | ||||
|     int bUseMagic = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EASY) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) return; | ||||
|         // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ | ||||
|         // Does our master want to be buffed first? | ||||
|         object oTarget = OBJECT_INVALID; | ||||
|         if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature); | ||||
|         int nRound = ai_GetCurrentRound(oCreature); | ||||
|         if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound, oTarget)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             // ******************* OFFENSIVE AOE TALENTS *********************** | ||||
|             // Check the battlefield for a group of enemies to shoot a big spell at! | ||||
|             // We are checking here since these opportunities are rare and we need | ||||
|             // to take advantage of them as often as possible. | ||||
|             if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|             { | ||||
|                 if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|                 if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|             } | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     // If we won't loose invisibility then ranged attacks are ok! | ||||
|     // ************************  RANGED ATTACKS  ******************************* | ||||
|     if(GetHasSpellEffect(SPELL_IMPROVED_INVISIBILITY) || GetHasSpellEffect(SPELLABILITY_AS_IMPROVED_INVISIBLITY)) | ||||
|     { | ||||
|         if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|         { | ||||
|             if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|             { | ||||
|                 // Are we suppose to protect our master first? | ||||
|                 if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) | ||||
|                 { | ||||
|                     // Lets pick off the weakest targets. | ||||
|                     if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                     else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|                 } | ||||
|                 if(oTarget != OBJECT_INVALID) | ||||
|                 { | ||||
|                     if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                     ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                     return; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|         } | ||||
|     } | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TrySneakAttack(oCreature, nInMelee)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         talent tUse = GetCreatureTalentBest(TALENT_CATEGORY_HARMFUL_MELEE, 20, oCreature); | ||||
|         if(GetIsTalentValid(tUse)) | ||||
|         { | ||||
|             int nId = GetIdFromTalent(tUse); | ||||
|             if(nId == FEAT_POWER_ATTACK) { if(ai_TryPowerAttackFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_KNOCKDOWN) { if(ai_TryKnockdownFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_SMITE_EVIL) { if(ai_TrySmiteEvilFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_SMITE_GOOD) { if(ai_TrySmiteGoodFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_IMPROVED_POWER_ATTACK) { if(ai_TryImprovedPowerAttackFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_FLURRY_OF_BLOWS) { if(ai_TryFlurryOfBlowsFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_STUNNING_FIST) { if(ai_TryStunningFistFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_SAP) { if(ai_TrySapFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_DISARM) { if(ai_TryDisarmFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_KI_DAMAGE) { if(ai_TryKiDamageFeat(oCreature, oTarget)) return; } | ||||
|             else if(nId == FEAT_CALLED_SHOT) { if(ai_TryCalledShotFeat(oCreature, oTarget)) return; } | ||||
|         } | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
|  | ||||
							
								
								
									
										82
									
								
								_module/nss/ai_a_monk.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								_module/nss/ai_a_monk.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_monk | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Monk class. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryWholenessOfBodyFeat(oCreature)) return; | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Are we suppose to protect our master first? | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 // Lets pick off the weakest targets. | ||||
|                 if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										131
									
								
								_module/nss/ai_a_no_cmb_mode.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								_module/nss/ai_a_no_cmb_mode.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_o_cmb_modes | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates to not use any combat modes during combat ai. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
|  Our actions. | ||||
|  1 - Get nearest enemy. | ||||
|  2 - Check for healing and curing first. | ||||
|  3 - Check moral if wounded and this is a simple+ battle. | ||||
|  4 - Check for a magical ranged attack if not in melee and a difficult+ battle. | ||||
|  5 - Check for a buff or summons if this is a difficult+ battle. | ||||
|  6 - Check for a Class ability and an offensive spell if this is a simple+ battle. | ||||
|  7 - Check for a physical attack. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         // ******************* OFFENSIVE AOE TALENTS *********************** | ||||
|         // Check the battlefield for a group of enemies to shoot a big spell at! | ||||
|         // We are checking here since these opportunities are rare and we need | ||||
|         // to take advantage of them as often as possible. | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) | ||||
|         { | ||||
|             // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ | ||||
|             // Does our master want to be buffed first? | ||||
|             object oTarget = OBJECT_INVALID; | ||||
|             if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature); | ||||
|             if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return; | ||||
|             if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; | ||||
|             if(ai_TryDivineMightFeat(oCreature, nInMelee)) return; | ||||
|         } | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_no_modes", "78", "Check for ranged attack on weakest enemy!"); | ||||
|     object oTarget; | ||||
|     int bAlwaysAtk = !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK); | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) && | ||||
|        !ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && | ||||
|        ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return; | ||||
|             // Lets pick off the weaker targets. | ||||
|             if(!nInMelee) | ||||
|             { | ||||
|                 if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE); | ||||
|                 if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 if(AI_DEBUG) ai_Debug("ai_a_no_modes", "105", GetName(OBJECT_SELF) + " does ranged attack on weakest: " + GetName(oTarget) + "!"); | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_no_modes", "117", "Check for melee attack on weakest enemy!"); | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TrySneakAttack(oCreature, nInMelee, bAlwaysAtk)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_PERCEPTION, bAlwaysAtk); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee, bAlwaysAtk); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(AI_DEBUG) ai_Debug("ai_a_no_modes", "126", GetName(OBJECT_SELF) + " does melee attack against weakest: " + GetName(oTarget) + "!"); | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
|  | ||||
							
								
								
									
										110
									
								
								_module/nss/ai_a_paladin.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								_module/nss/ai_a_paladin.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_paladin | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Paladin class. | ||||
|  Paladins always protect their masters and face the strongest opponents first! | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         // ******************* OFFENSIVE AOE TALENTS *********************** | ||||
|         // Check the battlefield for a group of enemies to shoot a big spell at! | ||||
|         // We are checking here since these opportunities are rare and we need | ||||
|         // to take advantage of them as often as possible. | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) | ||||
|         { | ||||
|             // ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************ | ||||
|             // Does our master want to be buffed first? | ||||
|             object oTarget = OBJECT_INVALID; | ||||
|             if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature); | ||||
|             if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return; | ||||
|             if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; | ||||
|             if(ai_TryDivineMightFeat(oCreature, nInMelee)) return; | ||||
|         } | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         if(ai_TryLayOnHands(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget = OBJECT_INVALID; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Paladins ALWAYS protect their masters first! | ||||
|             oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 // Paladins face off against the strongest opponents first. | ||||
|                 if(!nInMelee) oTarget = ai_GetHighestCRTarget(oCreature); | ||||
|                 else oTarget = ai_GetHighestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     // Paladins ALWAYS protect their masters first! | ||||
|     oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) | ||||
|     { | ||||
|         int bCheckCombat = ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK); | ||||
|         if(bCheckCombat) oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee, FALSE); | ||||
|         // If always attacking Paladins ALWAYS attack the strongest opponent. | ||||
|         else oTarget = ai_GetHighestCRTargetForMeleeCombat(oCreature, nInMelee); | ||||
|     } | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										81
									
								
								_module/nss/ai_a_peaceful.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								_module/nss/ai_a_peaceful.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: ai_a_peaceful | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script mode for associates to use when they should remain out of combat. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Programmer: Philos | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); | ||||
|     float fDistance = GetDistanceBetween(oCreature, oNearestEnemy); | ||||
|     // In Melee combat! | ||||
|     if(nInMelee > 0) | ||||
|     { | ||||
|         // If we are not being attacked then we should back out of combat. | ||||
|         if(ai_GetEnemyAttackingMe(oCreature) == OBJECT_INVALID) | ||||
|         { | ||||
|             if(AI_DEBUG) ai_Debug("ai_a_peaceful", "23", GetName(oCreature) + " is moving away from " + GetName(oNearestEnemy) + | ||||
|                          "[" + FloatToString(AI_RANGE_MELEE - fDistance + 1.0, 0, 2) + "]" + " to use a ranged weapon."); | ||||
|             ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE); | ||||
|             // Lets move just out of melee range! | ||||
|             int bRun = ai_CanIMoveInCombat(oCreature); | ||||
|             ActionMoveAwayFromObject(oNearestEnemy, bRun, AI_RANGE_CLOSE + 2.0); | ||||
|             ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); | ||||
|             return; | ||||
|         } | ||||
|         if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|         if(ai_TryImprovedExpertiseFeat(oCreature)) return; | ||||
|         if(ai_TryExpertiseFeat(oCreature)) return; | ||||
|         // Lets get the strongest melee opponent in melee with us. | ||||
|         object oTarget = ai_GetHighestCRTargetForMeleeCombat(oCreature, nInMelee); | ||||
|         if(oTarget == OBJECT_INVALID) oTarget = oNearestEnemy; | ||||
|         // Use knockdown when appropriate and the target is not immune. | ||||
|         if(ai_TryKnockdownFeat(oCreature, oTarget)) return; | ||||
|         if (ai_TryParry(oCreature)) return; | ||||
|         // We have tried everything to protect ourselves so the only thing left | ||||
|         // to do is man up and attack! | ||||
|         // Physical attacks are under TALENT_CATEGORY_HARMFUL_MELEE(22). | ||||
|         ai_DoPhysicalAttackOnNearest(oCreature, nInMelee); | ||||
|         return; | ||||
|     } | ||||
|     if(fDistance <= AI_RANGE_LONG) | ||||
|     { | ||||
|         if(AI_DEBUG) ai_Debug("ai_a_peaceful", "49", GetName(oCreature) + " is moving away from " + GetName(oNearestEnemy) + | ||||
|                      "[" + FloatToString(AI_RANGE_LONG - fDistance, 0, 2) + "]" + "."); | ||||
|         ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE); | ||||
|         // Lets move out of close range! | ||||
|         ActionMoveAwayFromObject(oNearestEnemy, TRUE, AI_RANGE_LONG + 2.0); | ||||
|         ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature)); | ||||
|         return; | ||||
|     } | ||||
|     //*************************  OUT OF COMBAT  ************************** | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, 0, oCreature)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, 0)) return; | ||||
|     //**************************  DEFENSIVE TALENTS  *************************** | ||||
|     // Has our master told us to not use magic? | ||||
|     int bUseMagic = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC); | ||||
|     if(bUseMagic) | ||||
|     { | ||||
|         // If can turn invisible then we should probably do that! | ||||
|         if(ai_UseTalent(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELL_INVISIBILITY, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELL_INVISIBILITY_SPHERE, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELL_SANCTUARY, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELL_ETHEREALNESS, oCreature)) return; // Greater Sanctuary | ||||
|         if(ai_UseTalent(oCreature, SPELLABILITY_AS_IMPROVED_INVISIBLITY, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELLABILITY_AS_INVISIBILITY, oCreature)) return; | ||||
|         int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|         // Summons are powerfull and should be used as much as possible. | ||||
|         if(ai_UseCreatureTalent(oCreature, AI_TALENT_SUMMON, nInMelee, nMaxLevel)) return; | ||||
|         if(ai_UseCreatureTalent(oCreature, AI_TALENT_PROTECTION, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Stand and watch the battle we don't want to provoke anyone! | ||||
|     if(AI_DEBUG) ai_Debug("ai_a_peaceful", "80", GetName(oCreature) + " is holding here."); | ||||
| } | ||||
							
								
								
									
										70
									
								
								_module/nss/ai_a_polymorphed.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								_module/nss/ai_a_polymorphed.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_polymorphed | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for polymorphed associates. | ||||
|  We check for abilities based on the form we are using and if we should polymorph back. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void ai_DoActions(object oCreature, int nForm) | ||||
| { | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     if(GetPercentageHPLoss(oCreature) <= AI_HEALTH_BLOODY) | ||||
|     { | ||||
|         //ai_Debug("ai_a_polymorphed", "24", "We are wounded and are transforming back!"); | ||||
|         ai_RemoveASpecificEffect(oCreature, EFFECT_TYPE_POLYMORPH); | ||||
|         return; | ||||
|     } | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // When polymorphed we turn back then check moral. | ||||
|         //if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee); | ||||
|     // If we don't find a target then we don't want to fight anyone! | ||||
|     if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Need to know who we are so we can use thier abilities. | ||||
|     int nForm = GetAppearanceType(oCreature); | ||||
|     // Check to see if we are back to our normal form?(-1 to get the actual form #) | ||||
|     if(nForm == GetLocalInt(oCreature, AI_NORMAL_FORM) - 1) | ||||
|     { | ||||
|         // If we are transformed back then go back to our primary ai. | ||||
|         ai_SetCreatureAIScript(oCreature); | ||||
|         DeleteLocalInt(oCreature, AI_NORMAL_FORM); | ||||
|         string sAI = GetLocalString(oCreature, AI_COMBAT_SCRIPT); | ||||
|         if(sAI == "ai_a_polymorphed" || sAI == "") sAI = "ai_a_default"; | ||||
|         ExecuteScript(sAI, oCreature); | ||||
|     } | ||||
|     else ai_DoActions(oCreature, nForm); | ||||
| } | ||||
							
								
								
									
										129
									
								
								_module/nss/ai_a_ranged.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								_module/nss/ai_a_ranged.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_ranged | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates to use the ranged ai. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
|  Will attempt to use ranged weapons until surrounded. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         // Turning is basically a powerful AOE so treat it like one. | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED)) | ||||
|     { | ||||
|         if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) && | ||||
|            nInMelee < 3) | ||||
|         { | ||||
|             if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|             { | ||||
|                 // Lets defend master, nearest favored enemy, ranged, sneak, weakest targets. | ||||
|                 if(!nInMelee) | ||||
|                 { | ||||
|                     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                     if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature); | ||||
|                     if(oTarget == OBJECT_INVALID) oTarget == ai_GetRangedTarget(oCreature); | ||||
|                     if(oTarget == OBJECT_INVALID && ai_TryRangedSneakAttack(oCreature, nInMelee)) return; | ||||
|                     if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|                     if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE); | ||||
|                     if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|                 } | ||||
|                 if(oTarget != OBJECT_INVALID) | ||||
|                 { | ||||
|                     if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                     ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                     return; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|         } | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); | ||||
|     if(nInMelee) | ||||
|     { | ||||
|         oTarget = ai_GetEnemyAttackingMe(oCreature); | ||||
|         if(oTarget != OBJECT_INVALID) | ||||
|         { | ||||
|             if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|             if(ai_TrySneakAttack(oCreature, nInMelee)) return; | ||||
|             if(ai_TryWhirlwindFeat(oCreature)) return; | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee); | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     if(oNearestEnemy != OBJECT_INVALID) | ||||
|     { | ||||
|         float fDistance = GetDistanceBetween(oCreature, oNearestEnemy); | ||||
|         float fRange = AI_RANGE_LONG; | ||||
|         if(GetIsAreaInterior(GetArea(oCreature))) fRange = AI_RANGE_CLOSE; | ||||
|         if(GetHasFeat(FEAT_SNEAK_ATTACK, oCreature)) fRange = AI_RANGE_CLOSE; | ||||
|         if(fDistance < fRange) | ||||
|          { | ||||
|             int bRun = ai_CanIMoveInCombat(oCreature); | ||||
|             ActionMoveAwayFromObject(oNearestEnemy, bRun, fRange - fDistance + 2.0); | ||||
|         } | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE); | ||||
| } | ||||
|  | ||||
							
								
								
									
										96
									
								
								_module/nss/ai_a_ranger.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								_module/nss/ai_a_ranger.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_ranger | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Ranger class. | ||||
|  Rangers will take out favored enemies first! | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Are we suppose to protect our master first? | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 // Lets pick off the weakest targets. | ||||
|                 if(!nInMelee) | ||||
|                 { | ||||
|                     oTarget = ai_GetNearestFavoredEnemyTarget(oCreature); | ||||
|                     if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE); | ||||
|                     if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|                 } | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     // Our master may have setup to check difficulty before we move into melee. | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_PERCEPTION, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										83
									
								
								_module/nss/ai_a_rogue.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								_module/nss/ai_a_rogue.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_rogue | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Rogue class. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Are we suppose to protect our master first? | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return; | ||||
|                 // Lets pick off the weakest targets. | ||||
|                 if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TrySneakAttack(oCreature, nInMelee)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										75
									
								
								_module/nss/ai_a_sorcerer.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								_module/nss/ai_a_sorcerer.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_sorcerer | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Sorcerer class. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Are we suppose to protect our master first? | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 // Lets pick off the weakest targets. | ||||
|                 if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										53
									
								
								_module/nss/ai_a_taunter.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								_module/nss/ai_a_taunter.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: ai_a_taunter | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures using defined to use the taunt skill. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Programmer: Philos | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         //**************************  SKILL FEATURES  ************************** | ||||
|         if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|         if(ai_TryBardSongFeat(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Class and Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TryTurningTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // Taunt the nearest target! | ||||
|     if (ai_TryTaunt (oCreature, ai_GetNearestTargetForMeleeCombat (oCreature, nInMelee))) return; | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     ai_DoPhysicalAttackOnLowestCR(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
| } | ||||
							
								
								
									
										77
									
								
								_module/nss/ai_a_wizard.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								_module/nss/ai_a_wizard.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_a_wizard | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for associates using the Wizard class. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     int nDifficulty = ai_GetDifficulty(oCreature); | ||||
|     int nMaxLevel; | ||||
|     // Check for moral and get the maximum spell level we should use. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty); | ||||
|     } | ||||
|     // Skill, Class, Offensive AOE's, and Defensive talents. | ||||
|     if(nDifficulty >= AI_COMBAT_MODERATE) | ||||
|     { | ||||
|         // ************************** CLASS FEATURES *************************** | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|         // *************************** SPELL TALENTS *************************** | ||||
|        if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     } | ||||
|     // Offensive single target talents. | ||||
|     if(nDifficulty >= AI_COMBAT_EFFORTLESS) | ||||
|     { | ||||
|         if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING)) | ||||
|         { | ||||
|             if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|             if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         } | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     // ************************** Ranged feat attacks ************************** | ||||
|     if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Are we suppose to protect our master first? | ||||
|             if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|             if(oTarget == OBJECT_INVALID) | ||||
|             { | ||||
|                 // Lets pick off the weakest targets. | ||||
|                 if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature); | ||||
|                 else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE); | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature); | ||||
|     if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK)); | ||||
|     if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     else ai_SearchForHiddenCreature(oCreature, FALSE); | ||||
| } | ||||
							
								
								
									
										100
									
								
								_module/nss/ai_ambusher.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								_module/nss/ai_ambusher.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_ambusher | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for ambushing creatures (Any). | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     // Rule used to disable ambush if the player wants to. | ||||
|     if(!GetLocalInt(GetModule(), AI_RULE_AMBUSH)) | ||||
|     { | ||||
|         ExecuteScript("ai_default", oCreature); | ||||
|         return; | ||||
|     } | ||||
|     // If can turn invisible then we should probably do that! | ||||
|     if(ai_UseTalent(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature)) return; | ||||
|     if(ai_UseTalent(oCreature, SPELL_INVISIBILITY, oCreature)) return; | ||||
|     if(ai_UseTalent(oCreature, SPELL_INVISIBILITY_SPHERE, oCreature)) return; | ||||
|     if(ai_UseTalent(oCreature, SPELL_SANCTUARY, oCreature)) return; | ||||
|     if(ai_UseTalent(oCreature, SPELL_ETHEREALNESS, oCreature)) return; // Greater Sanctuary | ||||
|     if(ai_UseTalent(oCreature, SPELLABILITY_AS_IMPROVED_INVISIBLITY, oCreature)) return; | ||||
|     if(ai_UseTalent(oCreature, SPELLABILITY_AS_INVISIBILITY, oCreature)) return; | ||||
|     // Check the battle field to see if anyone see us? | ||||
|     int nEnemyIndex = ai_GetNearestIndexThatSeesUs(oCreature); | ||||
|     // If seen, can we try to hide now? | ||||
|     if(nEnemyIndex) | ||||
|     { | ||||
|         // Check for an attacker and can they see through invisibility? | ||||
|         object oAttacker = ai_GetEnemyAttackingMe(oCreature); | ||||
|         int bCanSeeInvisible; | ||||
|         if(oAttacker != OBJECT_INVALID) | ||||
|         { | ||||
|             bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_SEEINVISIBLE); | ||||
|             if(!bCanSeeInvisible) bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_TRUESEEING); | ||||
|             if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_5_FEET, oCreature); | ||||
|             if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_10_FEET, oCreature); | ||||
|             if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_60_FEET, oCreature); | ||||
|         } | ||||
|         if(AI_DEBUG) ai_Debug("ai_ambusher", "43", "bCanSeeInvisible: " + IntToString(bCanSeeInvisible)); | ||||
|         if(!bCanSeeInvisible) | ||||
|         { | ||||
|             if(GetHasFeat(FEAT_HIDE_IN_PLAIN_SIGHT, oCreature)) | ||||
|             { | ||||
|                 if(!GetActionMode(oCreature, ACTION_MODE_STEALTH)) | ||||
|                 { | ||||
|                     if(AI_DEBUG) ai_Debug("ai_ambusher", "50", GetName(oCreature) + " is using hide in plain sight!"); | ||||
|                     ClearAllActions(TRUE); | ||||
|                     SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             // Does not have hide in plain sight. | ||||
|             else | ||||
|             { | ||||
|                 string sEnemyIndex = IntToString(nEnemyIndex); | ||||
|                 float fEnemyDistance = GetLocalFloat(oCreature, AI_ENEMY_RANGE + sEnemyIndex); | ||||
|                 if(AI_DEBUG) ai_Debug("ai_ambusher", "61", "fDistance: " + FloatToString(fEnemyDistance, 0, 2)); | ||||
|                 if(fEnemyDistance >= AI_RANGE_LONG) | ||||
|                 { | ||||
|                     int bTried = GetLocalInt(oCreature, AI_TRIED_TO_HIDE); | ||||
|                     if(!bTried) | ||||
|                     { | ||||
|                         // Move away so we can hide. | ||||
|                         if(AI_DEBUG) ai_Debug("ai_ambusher", "68", GetName(oCreature) + " is trying to move away to hide!"); | ||||
|                         SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); | ||||
|                         object oEnemy = GetLocalObject(oCreature, AI_ENEMY + sEnemyIndex); | ||||
|                         ActionMoveAwayFromObject(oEnemy, TRUE, AI_RANGE_BATTLEFIELD); | ||||
|                         SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3); | ||||
|                         return; | ||||
|                     } | ||||
|                     else SetLocalInt(oCreature, AI_TRIED_TO_HIDE, GetLocalInt(oCreature, AI_TRIED_TO_HIDE) - 1); | ||||
|                 } | ||||
|                 // We have been seen by an enemy too close to us so drop stealth. | ||||
|                 else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); | ||||
|             } | ||||
|         } | ||||
|         // The enemy can see through stealth so lets drop it. | ||||
|         else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); | ||||
|     } | ||||
|     // We are not in stealth mode so lets get there. | ||||
|     else if(!GetActionMode(oCreature, ACTION_MODE_STEALTH)) | ||||
|     { | ||||
|         // Use any hiding talents we have | ||||
|         if(AI_DEBUG) ai_Debug("ai_ambusher", "88", GetName(oCreature) + " is trying to hide!"); | ||||
|         SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); | ||||
|         SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3); | ||||
|         return; | ||||
|     } | ||||
|     // If we have givin up on stealth do our normal actions. | ||||
|     string sScript = GetLocalString(oCreature, AI_DEFAULT_SCRIPT); | ||||
|     if(sScript == "ai_ambusher" || sScript == "") sScript = "ai_default"; | ||||
|     if(AI_DEBUG) ai_Debug("ai_ambusher", "96", "sScript: " + sScript + " AI_DEFAULT_SCRIPT: " + GetLocalString(oCreature, AI_DEFAULT_SCRIPT)); | ||||
|     ExecuteScript(sScript, oCreature); | ||||
| } | ||||
							
								
								
									
										71
									
								
								_module/nss/ai_barbarian.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								_module/nss/ai_barbarian.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: ai_barbarian | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures using the class Barbarian. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Programmer: Philos | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     object oTarget; | ||||
|     if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature)) | ||||
|     { | ||||
|         //***************************  HEALING & CURES  **************************** | ||||
|         if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|         if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|         if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|         int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|         //*******************  OFFENSIVE AREA OF EFFECT TALENTS  ******************* | ||||
|         // Check the battlefield for a group of enemies to shoot a big talent at! | ||||
|         // We are checking here since these opportunities are rare and we need | ||||
|         // to take advantage of them as often as possible. | ||||
|         if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|         if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|         //****************************  CLASS FEATURES  **************************** | ||||
|         if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|         //**************************  DEFENSIVE TALENTS  *************************** | ||||
|         int nRound = ai_GetCurrentRound(oCreature); | ||||
|         if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; | ||||
|         //**********************  OFFENSIVE TARGETED TALENTS  ********************** | ||||
|         // Look for a touch attack since we are in melee. | ||||
|         if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|         if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|         // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|         // ***************************  RANGED ATTACKS  ***************************** | ||||
|         if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|         { | ||||
|             if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|             { | ||||
|                 if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature); | ||||
|                 else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); | ||||
|                 if(oTarget != OBJECT_INVALID) | ||||
|                 { | ||||
|                     if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                     ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                     return; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|         } | ||||
|     } | ||||
|     // *****************************  MELEE ATTACKS  *************************** | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TryWhirlwindFeat(oCreature)) return; | ||||
|     oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
| } | ||||
							
								
								
									
										67
									
								
								_module/nss/ai_bard.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								_module/nss/ai_bard.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: ai_bard | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures using the class Bard. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Programmer: Philos | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //*******************  OFFENSIVE AREA OF EFFECT TALENTS  ******************* | ||||
|     // Check the battlefield for a group of enemies to shoot a big talent at! | ||||
|     // We are checking here since these opportunities are rare and we need | ||||
|     // to take advantage of them as often as possible. | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     //****************************  CLASS FEATURES  **************************** | ||||
|     if(ai_TryBardSongFeat(oCreature)) return; | ||||
|     //**************************  DEFENSIVE TALENTS  *************************** | ||||
|     int nRound = ai_GetCurrentRound(oCreature); | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; | ||||
|     //**********************  OFFENSIVE TARGETED TALENTS  ********************** | ||||
|     // Look for a touch attack since we are in melee. | ||||
|     if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     // ************************  RANGED ATTACKS  ******************************* | ||||
|     object oTarget; | ||||
|     if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature); | ||||
|             else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // *************************  MELEE ATTACKS  ******************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
| } | ||||
							
								
								
									
										68
									
								
								_module/nss/ai_cleric.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								_module/nss/ai_cleric.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: ai_cleric | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures using the class Cleric. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Programmer: Philos | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //*******************  OFFENSIVE AREA OF EFFECT TALENTS  ******************* | ||||
|     // Check the battlefield for a group of enemies to shoot a big talent at! | ||||
|     // We are checking here since these opportunities are rare and we need | ||||
|     // to take advantage of them as often as possible. | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     //****************************  CLASS FEATURES  **************************** | ||||
|     if(ai_TryTurningTalent(oCreature)) return; | ||||
|     //**************************  DEFENSIVE TALENTS  *************************** | ||||
|     int nRound = ai_GetCurrentRound(oCreature); | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; | ||||
|     if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; | ||||
|     if(ai_TryDivineMightFeat(oCreature, nInMelee)) return; | ||||
|     //**********************  OFFENSIVE TARGETED TALENTS  ********************** | ||||
|     // Look for a touch attack since we are in melee. | ||||
|     if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     // ************************  RANGED ATTACKS  ******************************* | ||||
|     object oTarget; | ||||
|     if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature); | ||||
|             else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // *************************  MELEE ATTACKS  ******************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
| } | ||||
							
								
								
									
										68
									
								
								_module/nss/ai_cntrspell.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								_module/nss/ai_cntrspell.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_cntrspell | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures using the combat mode counter spell. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     // We are not in melee combat then we don't attack. | ||||
|     int bAttack = nInMelee; | ||||
|     if(!bAttack) | ||||
|     { | ||||
|         // If there are no casters, i.e. CLERIC or MAGES in the battle then attack. | ||||
|         struct stClasses stClasses = ai_GetFactionsClasses(oCreature); | ||||
|         if(!stClasses.CLERICS && !stClasses.MAGES) bAttack = TRUE; | ||||
|     } | ||||
|     // If we are not attacking then setup for counter spelling. | ||||
|     if(!bAttack) | ||||
|     { | ||||
|         //***************************  HEALING & CURES  **************************** | ||||
|         if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|         if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|         if(AI_DEBUG) ai_Debug("ai_cntrspell", "29", " Counterspell Mode? " + | ||||
|                      IntToString(GetActionMode(OBJECT_SELF, ACTION_MODE_COUNTERSPELL))); | ||||
|         if(!GetActionMode(oCreature, ACTION_MODE_COUNTERSPELL)) | ||||
|         { | ||||
|             object oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER); | ||||
|             // We can only counter spells from a hasted caster if we are hasted as well. | ||||
|             if(ai_GetHasEffectType(oTarget, EFFECT_TYPE_HASTE) && | ||||
|               !ai_GetHasEffectType(oCreature, EFFECT_TYPE_HASTE)) | ||||
|             { | ||||
|                 // If we have haste then we should cast it. | ||||
|                 if(GetHasSpell(SPELL_HASTE, oCreature)) | ||||
|                 { | ||||
|                     if(AI_DEBUG) ai_Debug("ai_cntrspell", "41", "Opponent is hasted! Casting Haste."); | ||||
|                     ActionCastSpellAtObject(SPELL_HASTE, oCreature); | ||||
|                     ai_SetLastAction(oCreature, SPELL_HASTE); | ||||
|                     return; | ||||
|                 } | ||||
|                 // If not then we need to go into normal combat. | ||||
|                 else | ||||
|                 { | ||||
|                     if(AI_DEBUG) ai_Debug("ai_cntrspell", "49", "Opponent is hasted! Using ranged AI."); | ||||
|                     ExecuteScript("ai_ranged"); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 // First a good tactic for counter spelling is to be invisible. | ||||
|                 if(ai_TryToBecomeInvisible(oCreature)) return; | ||||
|                 // If we have attempted to become invisible or are invisible then | ||||
|                 // it is time to counter spell. | ||||
|                 if(AI_DEBUG) ai_Debug("ai_cntrspell", "60", "Setting Counterspell mode!"); | ||||
|                 ActionCounterSpell(oTarget); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     if(AI_DEBUG) ai_Debug("ai_cntrspell", "66", "Situation is not good for counterspelling! Using ranged AI."); | ||||
|     ExecuteScript("ai_ranged"); | ||||
| } | ||||
							
								
								
									
										133
									
								
								_module/nss/ai_coward.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								_module/nss/ai_coward.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: ai_coward | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for cowardly creatures (Any) used when they fail a moral check or | ||||
|  when associates are to remain out of combat. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Programmer: Philos | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with us. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); | ||||
|     // If we have been healed up then get back in there! | ||||
|     if(ai_GetPercHPLoss(oCreature) > AI_HEALTH_WOUNDED) | ||||
|     { | ||||
|         string sDefaultCombatScript = GetLocalString(oCreature, AI_DEFAULT_SCRIPT); | ||||
|         SetLocalString(oCreature, AI_COMBAT_SCRIPT, sDefaultCombatScript); | ||||
|         ExecuteScript(sDefaultCombatScript, oCreature); | ||||
|         return; | ||||
|     } | ||||
|     // In Melee combat! | ||||
|     if(nInMelee) | ||||
|     { | ||||
|         if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|         if(ai_TryImprovedExpertiseFeat(oCreature)) return; | ||||
|         if(ai_TryExpertiseFeat(oCreature)) return; | ||||
|         // Lets get the strongest melee opponent in melee with us. | ||||
|         object oTarget = ai_GetHighestCRTargetForMeleeCombat(oCreature, nInMelee); | ||||
|         if(oTarget == OBJECT_INVALID) oTarget = oNearestEnemy; | ||||
|         // Use knockdown when appropriate and the target is not immune. | ||||
|         if(ai_TryKnockdownFeat(oCreature, oTarget)) return; | ||||
|         if (ai_TryParry(oCreature)) return; | ||||
|         // We have tried everything to protect ourselves so the only thing left | ||||
|         // to do is man up and attack! | ||||
|         // Physical attacks are under TALENT_CATEGORY_HARMFUL_MELEE(22). | ||||
|         ai_DoPhysicalAttackOnNearest(oCreature, nInMelee); | ||||
|         return; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // If can turn invisible then we should probably do that! | ||||
|         if(ai_UseTalent(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELL_INVISIBILITY, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELL_INVISIBILITY_SPHERE, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELL_SANCTUARY, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELL_ETHEREALNESS, oCreature)) return; // Greater Sanctuary | ||||
|         if(ai_UseTalent(oCreature, SPELLABILITY_AS_IMPROVED_INVISIBLITY, oCreature)) return; | ||||
|         if(ai_UseTalent(oCreature, SPELLABILITY_AS_INVISIBILITY, oCreature)) return; | ||||
|         // If we are seen by the enemy we need to move back so we can hide. | ||||
|         int nEnemyIndex = ai_GetNearestIndexThatSeesUs(oCreature); | ||||
|         if(nEnemyIndex) | ||||
|         { | ||||
|             // Check for an attacker and can they see through invisibility? | ||||
|             object oAttacker = ai_GetEnemyAttackingMe(oCreature); | ||||
|             int bCanSeeInvisible; | ||||
|             if(oAttacker != OBJECT_INVALID) | ||||
|             { | ||||
|                 bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_SEEINVISIBLE); | ||||
|                 if(!bCanSeeInvisible) bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_TRUESEEING); | ||||
|                 if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_5_FEET, oCreature); | ||||
|                 if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_10_FEET, oCreature); | ||||
|                 if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_60_FEET, oCreature); | ||||
|             } | ||||
|             if(!bCanSeeInvisible) | ||||
|             { | ||||
|                 if(GetHasFeat(FEAT_HIDE_IN_PLAIN_SIGHT, oCreature)) | ||||
|                 { | ||||
|                     if(!GetActionMode(oCreature, ACTION_MODE_STEALTH)) | ||||
|                     { | ||||
|                         if(AI_DEBUG) ai_Debug("ai_coward", "74", GetName(oCreature) + " is using hide in plain sight!"); | ||||
|                         ClearAllActions(TRUE); | ||||
|                         SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|                 // Does not have hide in plain sight. | ||||
|                 else | ||||
|                 { | ||||
|                     string sEnemyIndex = IntToString(nEnemyIndex); | ||||
|                     float fEnemyDistance = GetLocalFloat(oCreature, AI_ENEMY_RANGE + sEnemyIndex); | ||||
|                     if(AI_DEBUG) ai_Debug("ai_coward", "85", "fDistance: " + FloatToString(fEnemyDistance, 0, 2)); | ||||
|                     if(fEnemyDistance >= AI_RANGE_CLOSE) | ||||
|                     { | ||||
|                         int bTried = GetLocalInt(oCreature, AI_TRIED_TO_HIDE); | ||||
|                         if(!bTried) | ||||
|                         { | ||||
|                             // Move away so we can hide. | ||||
|                             if(AI_DEBUG) ai_Debug("ai_coward", "93", GetName(oCreature) + " is trying to move away to hide!"); | ||||
|                             SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); | ||||
|                             object oEnemy = GetLocalObject(oCreature, AI_ENEMY + sEnemyIndex); | ||||
|                             ActionMoveAwayFromObject(oEnemy, TRUE, AI_RANGE_BATTLEFIELD); | ||||
|                             SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3); | ||||
|                             return; | ||||
|                         } | ||||
|                         else SetLocalInt(oCreature, AI_TRIED_TO_HIDE, GetLocalInt(oCreature, AI_TRIED_TO_HIDE) - 1); | ||||
|                     } | ||||
|                     // We have been seen by an enemy near us so drop stealth. | ||||
|                     else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); | ||||
|                 } | ||||
|             } | ||||
|             // The enemy can see through stealth so lets drop it. | ||||
|             else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE); | ||||
|         } | ||||
|         // We are not in stealth mode so lets get there. | ||||
|         else if(!GetActionMode(oCreature, ACTION_MODE_STEALTH)) | ||||
|         { | ||||
|             // Use any hiding talents we have | ||||
|             if(AI_DEBUG) ai_Debug("ai_coward", "113", GetName(oCreature) + " is trying to hide!"); | ||||
|             SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE); | ||||
|             SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|     // Either we cannot go into stealth or we are in stealth so do something else. | ||||
|     //*************************  OUT OF MELEE COMBAT  ************************** | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, 0, oCreature)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, 0)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //**************************  DEFENSIVE TALENTS  *************************** | ||||
|     if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) | ||||
|     { | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|     } | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     // Stand and watch the battle we don't want to provoke anyone! | ||||
|     if(AI_DEBUG) ai_Debug("ai_coward", "132", GetName(oCreature) + " is holding here."); | ||||
| } | ||||
							
								
								
									
										50
									
								
								_module/nss/ai_default.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								_module/nss/ai_default.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_default | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for default creatures(Any). | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //*******************  OFFENSIVE AREA OF EFFECT TALENTS  ******************* | ||||
|     // Check the battlefield for a group of enemies to shoot a big talent at! | ||||
|     // We are checking here since these opportunities are rare and we need | ||||
|     // to take advantage of them as often as possible. | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     //****************************  SKILL FEATURES  **************************** | ||||
|     if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|     //****************************  CLASS FEATURES  **************************** | ||||
|     if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) | ||||
|     { | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|     } | ||||
|     //**************************  DEFENSIVE TALENTS  *************************** | ||||
|     int nRound = ai_GetCurrentRound(oCreature); | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; | ||||
|     if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return; | ||||
|     if(ai_TryDivineMightFeat(oCreature, nInMelee)) return; | ||||
|     //**********************  OFFENSIVE TARGETED TALENTS  ********************** | ||||
|     // Look for a touch attack since we are in melee. | ||||
|     if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|     //****************************  CLASS FEATURES  **************************** | ||||
|     if(ai_TryPolymorphSelfFeat(oCreature)) return; | ||||
|     if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|     if(ai_TryBardSongFeat(oCreature)) return; | ||||
|     if(ai_TryTurningTalent(oCreature)) return; | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     ai_DoPhysicalAttackOnNearest(oCreature, nInMelee); | ||||
| } | ||||
							
								
								
									
										48
									
								
								_module/nss/ai_defensive.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								_module/nss/ai_defensive.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_defensive | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures put in to a defensive mode to protect themselves(Any). | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //****************************  SKILL FEATURES  **************************** | ||||
|     if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|     //****************************  CLASS FEATURES  **************************** | ||||
|     if(ai_TryBardSongFeat(oCreature)) return; | ||||
|     if(ai_TryTurningTalent(oCreature)) return; | ||||
|     if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) | ||||
|     { | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|     } | ||||
|     //**************************  DEFENSIVE TALENTS  *************************** | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel)) return; | ||||
|     //********************  DEFENSIVE MELEE FEATS  ***************************** | ||||
|     if(nInMelee > 0) | ||||
|     { | ||||
|         if(ai_TryImprovedExpertiseFeat(oCreature)) return; | ||||
|         if(ai_TryExpertiseFeat(oCreature)) return; | ||||
|         // Lets get the strongest melee opponent in melee with us. | ||||
|         object oTarget = ai_GetHighestCRTargetForMeleeCombat(oCreature, nInMelee); | ||||
|         if(oTarget == OBJECT_INVALID) oTarget = oNearestEnemy; | ||||
|         // Use knockdown when appropriate and the target is not immune | ||||
|         if(ai_TryKnockdownFeat(oCreature, oTarget)) return; | ||||
|         if(ai_TryParry(oCreature)) return; | ||||
|     } | ||||
|     //**********************  PHYSICAL ATTACKS  ******************************** | ||||
|     // Even in defensive mode we want to be in battle so go find someone! | ||||
|     ai_DoPhysicalAttackOnNearest(oCreature, nInMelee); | ||||
| } | ||||
							
								
								
									
										51
									
								
								_module/nss/ai_dragon.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								_module/nss/ai_dragon.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_dragon | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for dragons. | ||||
|  OBJECT_SELF is the dragons running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     //***************************  HEALING & CURES  **************************** | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     // Dragons do not flee! if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //*******************  OFFENSIVE AREA OF EFFECT TALENTS  ******************* | ||||
|     // Check the battlefield for a group of enemies to shoot a big talent at! | ||||
|     // We are checking here since these opportunities are rare and we need | ||||
|     // to take advantage of them as often as possible. | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     //**************************  DEFENSIVE TALENTS  *************************** | ||||
|     int nRound = ai_GetCurrentRound(oCreature); | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; | ||||
|     //**********************  OFFENSIVE TARGETED TALENTS  ********************** | ||||
|     // Look for a touch attack since we are in melee. | ||||
|     if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|     // ************************  MELEE ATTACKS  ******************************** | ||||
|     object oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(GetDistanceBetween(oCreature, oTarget) > AI_RANGE_CLOSE) | ||||
|         { | ||||
|             // Can we do a crush attack(HD 18+)? | ||||
|             if(ai_TryCrushAttack(oCreature, oTarget)) return; | ||||
|             ai_FlyToTarget(oCreature, oTarget); | ||||
|             return; | ||||
|         } | ||||
|         if(ai_TryDragonBreathAttack(oCreature, nRound)) return; | ||||
|         ai_TryWingAttacks(oCreature); | ||||
|         // If we don't do a Tail sweep attack(HD 30+) then see if we can do a Tail slap(HD 12+)! | ||||
|         if(!ai_TryTailSweepAttack(oCreature)) ai_TryTailSlap(oCreature); | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
| } | ||||
							
								
								
									
										70
									
								
								_module/nss/ai_druid.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								_module/nss/ai_druid.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_druid | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures using the class Druid. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //*******************  OFFENSIVE AREA OF EFFECT TALENTS  ******************* | ||||
|     // Check the battlefield for a group of enemies to shoot a big talent at! | ||||
|     // We are checking here since these opportunities are rare and we need | ||||
|     // to take advantage of them as often as possible. | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     //****************************  CLASS FEATURES  **************************** | ||||
|     if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS) && ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|     if(ai_TryPolymorphSelfFeat(oCreature)) return; | ||||
|     //**************************  DEFENSIVE TALENTS  *************************** | ||||
|     int nRound = ai_GetCurrentRound(oCreature); | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; | ||||
|     //**********************  OFFENSIVE TARGETED TALENTS  ********************** | ||||
|     // Look for a touch attack since we are in melee. | ||||
|     if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|     //****************************  SKILL FEATURES  **************************** | ||||
|     if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|     // All else fails lets see if we have any good potions. | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     // ************************  RANGED ATTACKS  ******************************* | ||||
|     object oTarget; | ||||
|     if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             // Lets pick off the nearest targets. | ||||
|             if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature); | ||||
|             else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // *************************  MELEE ATTACKS  ******************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee); | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
| } | ||||
							
								
								
									
										65
									
								
								_module/nss/ai_fighter.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								_module/nss/ai_fighter.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| /*////////////////////////////////////////////////////////////////////////////// | ||||
|  Script Name: ai_fighter | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures using the class Fighter. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  Programmer: Philos | ||||
| */////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange (oCreature); | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //*****************  OFFENSIVE AREA OF EFFECT TALENTS  ********************* | ||||
|     // Check the battlefield for a group of enemies to shoot a big talent at! | ||||
|     // We are checking here since these opportunities are rare and we need | ||||
|     // to take advantage of them as often as possible. | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     // ***********************  DEFENSIVE TALENTS  ***************************** | ||||
|     int nRound = ai_GetCurrentRound(oCreature); | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; | ||||
|     //*******************  OFFENSIVE TARGETED TALENTS  ************************* | ||||
|     // Look for a touch attack since we are in melee. | ||||
|     if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     // ***************************  RANGED ATTACKS  **************************** | ||||
|     object oTarget; | ||||
|     if(ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature); | ||||
|             else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // ****************************  MELEE ATTACKS  **************************** | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     if(ai_TryWhirlwindFeat (oCreature)) return; | ||||
|     oTarget = ai_GetNearestTargetForMeleeCombat (oCreature, nInMelee); | ||||
|     if (oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_TryMeleeTalents (oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
| } | ||||
							
								
								
									
										102
									
								
								_module/nss/ai_flanker.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								_module/nss/ai_flanker.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_flanker | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for monsters to flank the enemy and not charge into combat. | ||||
|  OBJECT_SELF is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange(oCreature); | ||||
|     if(ai_TryHealingTalent(oCreature, nInMelee)) return; | ||||
|     if(ai_TryCureConditionTalent(oCreature, nInMelee)) return; | ||||
|     if(nInMelee && ai_MoralCheck(oCreature)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //*****************  OFFENSIVE AREA OF EFFECT TALENTS  ********************* | ||||
|     // Check the battlefield for a group of enemies to shoot a big talent at! | ||||
|     // We are checking here since these opportunities are rare and we need | ||||
|     // to take advantage of them as often as possible. | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     // ***********************  DEFENSIVE TALENTS  ***************************** | ||||
|     int nRound = ai_GetCurrentRound(oCreature); | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; | ||||
|     //*******************  OFFENSIVE TARGETED TALENTS  ************************* | ||||
|     // Look for a touch attack since we are in melee. | ||||
|     if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|     //****************************  SKILL FEATURES  **************************** | ||||
|     if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|     //****************************  CLASS FEATURES  **************************** | ||||
|     if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|     if(ai_TryBardSongFeat(oCreature)) return; | ||||
|     if(ai_TryTurningTalent(oCreature)) return; | ||||
|     if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS)) | ||||
|     { | ||||
|         if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|         if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|     } | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     object oTarget; | ||||
|     // ************************** Melee feat attacks ************************* | ||||
|     // Lets get the nearest target that is attacking someone besides me. We want to flank! | ||||
|     if(oTarget == OBJECT_INVALID) | ||||
|     { | ||||
|         if(!nInMelee) oTarget = ai_GetFlankTarget(oCreature); | ||||
|         // If there are few enemies then we can safely move around. | ||||
|         else if(nInMelee < 3 || ai_CanIMoveInCombat(oCreature)) | ||||
|         { | ||||
|             oTarget = ai_GetFlankTarget(oCreature, AI_RANGE_MELEE); | ||||
|         } | ||||
|         // Ok we are in a serious fight so lets not give attack of opportunities. | ||||
|         else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE); | ||||
|     } | ||||
|     // If there are no enemies being attacked then lets stay back. | ||||
|     if(oTarget == OBJECT_INVALID) | ||||
|     { | ||||
|         if(nInMelee) | ||||
|         { | ||||
|             if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|             // Lets get the strongest melee opponent in melee with us. | ||||
|             object oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee); | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         // ************************** Ranged feat attacks ************************** | ||||
|         if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|         { | ||||
|             if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|             { | ||||
|                 if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return; | ||||
|                 oTarget = ai_GetNearestTarget(oCreature); | ||||
|                 if(oTarget != OBJECT_INVALID) | ||||
|                 { | ||||
|                     if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return; | ||||
|                     ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     if(oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|         if(ai_TryMeleeTalents(oCreature, oTarget)) return; | ||||
|         ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|         return; | ||||
|     } | ||||
|     ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE); | ||||
| } | ||||
							
								
								
									
										83
									
								
								_module/nss/ai_incorporeal.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								_module/nss/ai_incorporeal.nss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| /*//////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Script Name: ai_incorporeal | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  ai script for creatures that are incorporeal. | ||||
|  oCreature is the creature running the ai. | ||||
| *///////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Programmer: Philos | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| #include "0i_actions" | ||||
| void main() | ||||
| { | ||||
|     object oCreature = OBJECT_SELF; | ||||
|     // Get the number of enemies that we are in melee combat with. | ||||
|     int nInMelee = ai_GetNumOfEnemiesInRange (oCreature); | ||||
|     if (nInMelee && ai_MoralCheck (oCreature)) return; | ||||
|     int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature); | ||||
|     //*******************  OFFENSIVE AREA OF EFFECT TALENTS  ******************* | ||||
|     // Check the battlefield for a group of enemies to shoot a big talent at! | ||||
|     // We are checking here since these opportunities are rare and we need | ||||
|     // to take advantage of them as often as possible. | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return; | ||||
|     //****************************  SKILL FEATURES  **************************** | ||||
|     if(ai_TryAnimalEmpathy(oCreature)) return; | ||||
|     //****************************  CLASS FEATURES  **************************** | ||||
|     if(ai_TryBarbarianRageFeat(oCreature)) return; | ||||
|     if(ai_TryBardSongFeat(oCreature)) return; | ||||
|     if(ai_TryTurningTalent(oCreature)) return; | ||||
|     if(ai_TrySummonAnimalCompanionTalent(oCreature)) return; | ||||
|     if(ai_TrySummonFamiliarTalent(oCreature)) return; | ||||
|     //**************************  DEFENSIVE TALENTS  *************************** | ||||
|     int nRound = ai_GetCurrentRound(oCreature); | ||||
|     if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return; | ||||
|     //**********************  OFFENSIVE TARGETED TALENTS  ********************** | ||||
|     // Look for a touch attack since we are in melee. | ||||
|     if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return; | ||||
|     if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return; | ||||
|     // PHYSICAL ATTACKS - Either we don't have talents or we are saving them. | ||||
|     // ************************  RANGED ATTACKS  ******************************* | ||||
|     object oTarget; | ||||
|     if (!GetHasFeatEffect (FEAT_BARBARIAN_RAGE, oCreature) && ai_CanIUseRangedWeapon(oCreature, nInMelee)) | ||||
|     { | ||||
|         if(ai_HasRangedWeaponWithAmmo(oCreature)) | ||||
|         { | ||||
|             if (ai_TryRangedSneakAttack (oCreature, nInMelee)) return; | ||||
|             string sIndex; | ||||
|             if (!nInMelee) oTarget = ai_GetNearestTarget(oCreature); | ||||
|             else oTarget = ai_GetNearestTarget (oCreature, AI_RANGE_MELEE); | ||||
|             if(oTarget != OBJECT_INVALID) | ||||
|             { | ||||
|                 if(ai_TryRapidShotFeat (oCreature, oTarget, nInMelee)) return; | ||||
|                 ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         if(ai_InCombatEquipBestRangedWeapon(oCreature)) return; | ||||
|     } | ||||
|     // *************************  MELEE ATTACKS  ******************************* | ||||
|     if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return; | ||||
|     oTarget = ai_GetNearestTargetForMeleeCombat (oCreature, nInMelee); | ||||
|     if (oTarget != OBJECT_INVALID) | ||||
|     { | ||||
|         // If we are using our hands then do a touch attack instead. | ||||
|         if (GetItemInSlot (INVENTORY_SLOT_RIGHTHAND) == OBJECT_INVALID) | ||||
|         { | ||||
|             if (GetItemInSlot (INVENTORY_SLOT_CWEAPON_L) != OBJECT_INVALID) | ||||
|             { | ||||
|                 // Randomize so they don't appear synchronized. | ||||
|                 float fDelay = IntToFloat(Random(2) + 1); | ||||
|                 DelayCommand(fDelay, ActionCastSpellAtObject (769/*Shadow_Attack*/, oTarget, METAMAGIC_ANY, TRUE)); | ||||
|                 ai_SetLastAction(oCreature, AI_LAST_ACTION_MELEE_ATK); | ||||
|                 SetLocalObject (oCreature, AI_ATTACKED_PHYSICAL, oTarget); | ||||
|             } | ||||
|         } | ||||
|         else ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget); | ||||
|     } | ||||
|     else ai_SearchForHiddenCreature(oCreature, TRUE); | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user