/*////////////////////////////////////////////////////////////////////////////// // 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; }