794 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			794 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /*//////////////////////////////////////////////////////////////////////////////
 | |
| // 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;
 | |
| }
 |