2025/12/16 Update
Updated PEPS Hooked up new GUI module event. Updated classes.2da Updated baseitems.2da Updated nim tools. Full compile.
This commit is contained in:
@@ -17,10 +17,21 @@ void main()
|
||||
// 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);
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_SCOUT_AHEAD))
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
ai_HaveCreatureSpeak(oAssociate, 6, ":29:35:46:10");
|
||||
ai_SetAIMode(oAssociate, AI_MODE_SCOUT_AHEAD, FALSE);
|
||||
ai_SendMessages(GetName(oAssociate) + " has stopped patrolling ahead.", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
ai_HaveCreatureSpeak(oAssociate, 6, ":29:35:46:22:");
|
||||
ai_SetAIMode(oAssociate, AI_MODE_SCOUT_AHEAD, TRUE);
|
||||
ai_SendMessages(GetName(oAssociate) + " is now patrolling ahead.", AI_COLOR_YELLOW, oPC);
|
||||
ai_ScoutAhead(oAssociate);
|
||||
}
|
||||
}
|
||||
else if(sAction == "BasicTactics")
|
||||
{
|
||||
@@ -168,5 +179,22 @@ void main()
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(sAction == "GetHenchTokens")
|
||||
{
|
||||
int nCount, nCntr = 1;
|
||||
object oHenchman = GetHenchman(oPC, nCntr);
|
||||
while(oHenchman != OBJECT_INVALID && nCntr <= AI_MAX_HENCHMAN)
|
||||
{
|
||||
if(oHenchman == OBJECT_INVALID) break;
|
||||
if(oHenchman != oAssociate)
|
||||
{
|
||||
SetCustomToken(77101 + nCount, GetName(oHenchman));
|
||||
nCount++;
|
||||
}
|
||||
oHenchman = GetHenchman(oPC, ++nCntr);
|
||||
}
|
||||
ai_SetupAllyTargets(oAssociate, oPC);
|
||||
return;
|
||||
}
|
||||
aiSaveAssociateModesToDb(oPC, oAssociate);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
Allows use of ai_conversation for henchman in other modules.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_actions"
|
||||
#include "nw_inc_gff"
|
||||
void BeginOriginalHenchmanConversation(string sDialog, object oPC)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0c_get_convo", "14", "sDialog: (" + sDialog + ")");
|
||||
BeginConversation(sDialog, oPC);
|
||||
}
|
||||
void main()
|
||||
|
||||
@@ -32,6 +32,7 @@ void main()
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
object oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget));
|
||||
if(AI_DEBUG) ai_Debug("0c_henchmenspell", "36", " nTarget: " + IntToString(nTarget) + " oTarget: " + GetName(oTarget));
|
||||
if(oTarget != OBJECT_INVALID && ai_CheckAndCastSpell(oCreature, nSpell, 0, 0.0f, oTarget, oPC))
|
||||
{
|
||||
DeleteLocalInt(oCreature, "0_SPELL_TO_CAST");
|
||||
|
||||
16
_module/nss/0c_if_hen_target.nss
Normal file
16
_module/nss/0c_if_hen_target.nss
Normal file
@@ -0,0 +1,16 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_assoc_mode
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see the ally targets have been set for
|
||||
this number target.
|
||||
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.
|
||||
Param:
|
||||
nTarget - The target to check and see if they are set.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
int StartingConditional()
|
||||
{
|
||||
string sTarget = GetScriptParam("nTarget");
|
||||
return GetIsObjectValid(GetLocalObject(OBJECT_SELF, "AI_ALLY_TARGET_" + sTarget));
|
||||
}
|
||||
@@ -5,7 +5,11 @@
|
||||
Text Appears When script that checks if the speaker is the master of this
|
||||
henchman.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_constants"
|
||||
int StartingConditional()
|
||||
{
|
||||
return !GetIsObjectValid(GetMaster());
|
||||
string sInput = GetScriptParam("sInput");
|
||||
if(sInput == "Can_Hire_Henchman" && AI_ALLOW_TAKING_HENCHMAN) return !GetIsObjectValid(GetMaster());
|
||||
else if(sInput == "Cannot_Hire_Henchman") return !GetIsObjectValid(GetMaster());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,14 @@
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that check if scouting is activated on this server.
|
||||
|
||||
Script Param: nTRUE -
|
||||
if set to 1 then it will pass TRUE if they are in scout mode.
|
||||
if set to 0 then it will pass TRUE if they are NOT in scout mode.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
return AI_SCOUT_AHEAD_ON;
|
||||
int nTRUE = StringToInt(GetScriptParam("nTRUE"));
|
||||
return AI_SCOUT_AHEAD_ON && ai_GetAIMode(OBJECT_SELF, AI_MODE_SCOUT_AHEAD) == nTRUE;
|
||||
}
|
||||
|
||||
26
_module/nss/0e_animations.nss
Normal file
26
_module/nss/0e_animations.nss
Normal file
@@ -0,0 +1,26 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_animations
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Monster Ambient Animations and Walk Waypoint code.
|
||||
This code uses the Bioware systems, but can be rewritten to use what ever you
|
||||
want!
|
||||
This is called in the nw_c2_default1 - monster heartbeat script.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "x0_i0_anims"
|
||||
#include "0i_actions"
|
||||
void main()
|
||||
{
|
||||
if(!IsInConversation (OBJECT_SELF))
|
||||
{
|
||||
if(GetWalkCondition(NW_WALK_FLAG_CONSTANT)) WalkWayPoints();
|
||||
if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS)) PlayMobileAmbientAnimations_NonAvian();
|
||||
else if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN)) PlayMobileAmbientAnimations_Avian();
|
||||
else if(GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS)) PlayImmobileAmbientAnimations();
|
||||
else if(GetLocalInt(GetModule(), AI_RULE_WANDER) && GetStandardFactionReputation(STANDARD_FACTION_HOSTILE) > 89)
|
||||
{
|
||||
ai_AmbientAnimations();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -236,10 +236,10 @@ void main()
|
||||
{
|
||||
int nMaxHenchmen = StringToInt(sText);
|
||||
if(nMaxHenchmen < 1) nMaxHenchmen = 1;
|
||||
if(nMaxHenchmen > 12)
|
||||
if(nMaxHenchmen > AI_MAX_HENCHMAN)
|
||||
{
|
||||
nMaxHenchmen = 12;
|
||||
ai_SendMessages("The maximum henchmen for this mod is 12!", AI_COLOR_RED, oPC);
|
||||
nMaxHenchmen = AI_MAX_HENCHMAN;
|
||||
ai_SendMessages("The maximum henchmen for this mod is " + IntToString(AI_MAX_HENCHMAN) + "!", AI_COLOR_RED, oPC);
|
||||
}
|
||||
SetMaxHenchmen(nMaxHenchmen);
|
||||
SetLocalInt(oModule, AI_RULE_MAX_HENCHMAN, nMaxHenchmen);
|
||||
@@ -274,7 +274,7 @@ void main()
|
||||
{
|
||||
int nNumber = StringToInt(sText);
|
||||
if(nNumber < 0) nNumber = 0;
|
||||
else if(nNumber > 100) nNumber = 100;
|
||||
else if(nNumber > 500) nNumber = 500;
|
||||
SetLocalInt(oModule, AI_INCREASE_MONSTERS_HP, nNumber);
|
||||
jRules = JsonObjectSet(jRules, AI_INCREASE_MONSTERS_HP, JsonInt(nNumber));
|
||||
}
|
||||
@@ -310,6 +310,12 @@ void main()
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_BUFF_MONSTERS, JsonInt(bCheck));
|
||||
NuiSetBind(oPC, nToken, "chbx_full_buff_event", JsonBool(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_full_buff_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_FULL_BUFF_MONSTERS, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_FULL_BUFF_MONSTERS, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_buff_summons_check")
|
||||
{
|
||||
@@ -652,6 +658,9 @@ void main()
|
||||
if(sElem == "btn_cmd_follow" &&
|
||||
oPC != oAssociate) ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType);
|
||||
else if(sElem == "btn_follow_target") ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType);
|
||||
else if(sElem == "btn_buff_long") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
|
||||
else if(sElem == "btn_buff_short") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
|
||||
else if(sElem == "btn_buff_all") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
|
||||
}
|
||||
else if(nMouseScroll == -1.0) // Scroll down
|
||||
{
|
||||
@@ -659,6 +668,9 @@ void main()
|
||||
if(sElem == "btn_cmd_follow" &&
|
||||
oPC != oAssociate) ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType);
|
||||
else if(sElem == "btn_follow_target") ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType);
|
||||
else if(sElem == "btn_buff_long") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
|
||||
else if(sElem == "btn_buff_short") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
|
||||
else if(sElem == "btn_buff_all") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -955,6 +967,9 @@ void main()
|
||||
else if(sElem == "btn_heal_in") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType);
|
||||
else if(sElem == "btn_loot") ai_LootRangeIncrement(oPC, oAssociate, 1.0, sAssociateType);
|
||||
else if(sElem == "btn_perc_range") ai_PercRangeIncrement(oPC, oAssociate, 1, sAssociateType, -1);
|
||||
else if(sElem == "btn_buff_long") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
|
||||
else if(sElem == "btn_buff_short") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
|
||||
else if(sElem == "btn_buff_all") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
|
||||
}
|
||||
if(nMouseScroll == -1.0) // Scroll down
|
||||
{
|
||||
@@ -971,6 +986,9 @@ void main()
|
||||
else if(sElem == "btn_heal_in") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType);
|
||||
else if(sElem == "btn_loot") ai_LootRangeIncrement(oPC, oAssociate, -1.0, sAssociateType);
|
||||
else if(sElem == "btn_perc_range") ai_PercRangeIncrement(oPC, oAssociate, -1, sAssociateType, -1);
|
||||
else if(sElem == "btn_buff_long") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
|
||||
else if(sElem == "btn_buff_short") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
|
||||
else if(sElem == "btn_buff_all") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
|
||||
}
|
||||
}
|
||||
if(sEvent == "mousedown")
|
||||
@@ -1248,9 +1266,10 @@ void main()
|
||||
{
|
||||
json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_buffing");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_forcerest");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_henchmen");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_crafting");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_forcerest");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_fast_travel");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_henchmen");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_mod_set");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_debug");
|
||||
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_test");
|
||||
|
||||
@@ -208,10 +208,10 @@ void main()
|
||||
{
|
||||
int nMaxHenchmen = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
|
||||
if(nMaxHenchmen < 1) nMaxHenchmen = 1;
|
||||
if(nMaxHenchmen > 12)
|
||||
if(nMaxHenchmen > AI_MAX_HENCHMAN)
|
||||
{
|
||||
nMaxHenchmen = 12;
|
||||
ai_SendMessages("The maximum henchmen for this mod is 12!", AI_COLOR_RED, oDM);
|
||||
nMaxHenchmen = AI_MAX_HENCHMAN;
|
||||
ai_SendMessages("The maximum henchmen for this mod is " + IntToString(AI_MAX_HENCHMAN) + "!", AI_COLOR_RED, oDM);
|
||||
}
|
||||
SetMaxHenchmen(nMaxHenchmen);
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
@@ -243,7 +243,7 @@ void main()
|
||||
{
|
||||
int nNumber = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
|
||||
if(nNumber < 0) nNumber = 0;
|
||||
else if(nNumber > 100) nNumber = 100;
|
||||
else if(nNumber > 500) nNumber = 500;
|
||||
SetLocalInt(GetModule(), AI_INCREASE_MONSTERS_HP, nNumber);
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
jRules = JsonObjectSet(jRules, AI_INCREASE_MONSTERS_HP, JsonInt(nNumber));
|
||||
@@ -264,6 +264,11 @@ void main()
|
||||
SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_BUFF_MONSTERS, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_full_buff_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_FULL_BUFF_MONSTERS, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_FULL_BUFF_MONSTERS, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_buff_summons_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_PRESUMMON, bCheck);
|
||||
|
||||
@@ -14,13 +14,6 @@
|
||||
AI_TARGET_MODE_ON defines if the player is in target mode for a henchman instead of the PC.
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_player_target"
|
||||
void ai_EnterAssociateTargetMode(object oPC, object oAssociate)
|
||||
{
|
||||
SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate);
|
||||
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION");
|
||||
SetLocalInt(oPC, AI_TARGET_MODE_ON, TRUE);
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
|
||||
}
|
||||
void main()
|
||||
{
|
||||
object oPC = GetLastPlayerToSelectTarget();
|
||||
@@ -40,6 +33,7 @@ void main()
|
||||
location lLocation = Location(GetArea(oPC), vTarget, GetFacing(oPC));
|
||||
object oAssociate = GetLocalObject(oPC, AI_TARGET_ASSOCIATE);
|
||||
string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE);
|
||||
DeleteLocalString(oPC, AI_TARGET_MODE);
|
||||
// ********************* Exiting Target Actions ************************
|
||||
// If the user manually exited targeting mode without selecting a target, return
|
||||
if(!GetIsObjectValid(oTarget) && vTarget == Vector())
|
||||
@@ -47,11 +41,8 @@ void main()
|
||||
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);
|
||||
ai_RemoveAllActionMode(oPC);
|
||||
return;
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_ACTION")
|
||||
{
|
||||
@@ -67,41 +58,33 @@ void main()
|
||||
AttachCamera(oPC, oPC);
|
||||
if(!GetLocalInt(GetModule(), AI_USING_PRC)) ai_TurnOff(oPC, oPC, "pc");
|
||||
}
|
||||
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
|
||||
ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, FALSE);
|
||||
if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) && !ai_GetAIMode(oPC, AI_MODE_GHOST) &&
|
||||
GetLocalInt(oAssociate, sGhostModeVarname))
|
||||
{
|
||||
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);
|
||||
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
|
||||
DeleteLocalInt(oAssociate, sGhostModeVarname);
|
||||
}
|
||||
ExecuteScript("nw_ch_ac1", oAssociate);
|
||||
return;
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_GET_TRAP")
|
||||
{
|
||||
ai_SendMessages(GetName(oAssociate) + " has exited selecing a trap!", AI_COLOR_YELLOW, oPC);
|
||||
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
|
||||
return;
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_PLACE_TRAP")
|
||||
{
|
||||
ai_SendMessages(GetName(oAssociate) + " has exited placing the trap!", AI_COLOR_YELLOW, oPC);
|
||||
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
// If these actions are canceled and we are in target mode with a henchmen
|
||||
// then turn target mode back on for that henchmen.
|
||||
@@ -111,8 +94,8 @@ void main()
|
||||
sTargetMode == "ASSOCIATE_FOLLOW_TARGET")
|
||||
{
|
||||
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// ************************* Targeted Actions **************************
|
||||
else
|
||||
@@ -120,29 +103,38 @@ void main()
|
||||
// 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);
|
||||
ai_ActionAllAssociates(oPC, oTarget, lLocation);
|
||||
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION_ALL");
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
|
||||
return;
|
||||
}
|
||||
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));
|
||||
AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation));
|
||||
return;
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_FOLLOW_TARGET")
|
||||
{
|
||||
ai_SelectFollowTarget(oPC, oAssociate, oTarget);
|
||||
return;
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_GET_TRAP")
|
||||
{
|
||||
ai_SelectTrap(oPC, oAssociate, oTarget);
|
||||
return;
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_PLACE_TRAP")
|
||||
{
|
||||
AssignCommand(oAssociate, ai_PlaceTrap(oPC, lLocation));
|
||||
return;
|
||||
}
|
||||
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));
|
||||
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
|
||||
return;
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_USE_FEAT")
|
||||
{
|
||||
@@ -150,6 +142,7 @@ void main()
|
||||
ai_UseWidgetFeat(oPC, oAssociate, oTarget, lLocation);
|
||||
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
|
||||
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
|
||||
return;
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_CAST_SPELL")
|
||||
{
|
||||
@@ -157,11 +150,13 @@ void main()
|
||||
ai_CastWidgetSpell(oPC, oAssociate, oTarget, lLocation);
|
||||
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
|
||||
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
|
||||
return;
|
||||
}
|
||||
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);
|
||||
return;
|
||||
}
|
||||
else if(sTargetMode == "DM_SELECT_OPEN_INVENTORY")
|
||||
{
|
||||
@@ -171,17 +166,20 @@ void main()
|
||||
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);
|
||||
return;
|
||||
}
|
||||
else if(GetStringLeft(sTargetMode, 15) == "DM_SELECT_GROUP")
|
||||
{
|
||||
ai_AddToGroup(oPC, oTarget, sTargetMode);
|
||||
return;
|
||||
}
|
||||
else if(GetStringLeft(sTargetMode, 15) == "DM_ACTION_GROUP")
|
||||
{
|
||||
ai_DMAction(oPC, oTarget, lLocation, sTargetMode);
|
||||
return;
|
||||
}
|
||||
// Get saved module player target script and execute it for pass through compatibility.
|
||||
ExecuteScript(GetLocalString(GetModule(), AI_MODULE_TARGET_EVENT));
|
||||
}
|
||||
// Get saved module player target script and execute it for pass through compatibility.
|
||||
ExecuteScript(GetLocalString(GetModule(), AI_MODULE_TARGET_EVENT));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID
|
||||
{
|
||||
SetLocalInt(oCreature, AI_POLYMORPHED, TRUE);
|
||||
ai_ClearTalents(oCreature);
|
||||
ai_SetCreatureSpecialAbilityTalents(oCreature, FALSE, TRUE);
|
||||
ai_SetCreatureSpecialAbilityTalents(oCreature, FALSE, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,6 +219,7 @@ void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID
|
||||
void ai_StartAssociateCombat(object oAssociate, object oTarget = OBJECT_INVALID)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "217", "---------- " + GetName(oAssociate) + " is starting combat! ----------");
|
||||
//ai_SetCreatureTalentsByLevel(oAssociate, FALSE);
|
||||
ai_SetCreatureTalents(oAssociate, FALSE);
|
||||
ai_CheckXPPartyScale(oAssociate);
|
||||
ai_DoAssociateCombatRound(oAssociate, oTarget);
|
||||
@@ -249,7 +250,7 @@ void ai_DoMonsterCombatRound(object oMonster)
|
||||
{
|
||||
SetLocalInt(oMonster, AI_POLYMORPHED, TRUE);
|
||||
ai_ClearTalents(oMonster);
|
||||
ai_SetCreatureSpecialAbilityTalents(oMonster, TRUE, TRUE);
|
||||
ai_SetCreatureSpecialAbilityTalents(oMonster, TRUE, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -410,9 +411,20 @@ int ai_SearchForHiddenCreature(object oCreature, int bMonster, object oInvisible
|
||||
}
|
||||
}
|
||||
float fPerceptionDistance, fDistance;
|
||||
// Check to see if the creature is invisible because we cannot hurt them with our weapon.
|
||||
// If so we need to stay away from them! Maybe add weapon swapping code later?
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "415", GetName(oCreature) + "IsWeaponEffective? " +
|
||||
IntToString(GetIsWeaponEffective(oInvisible)) + " oInvisible: " + GetName(oInvisible));
|
||||
/*if(!GetIsWeaponEffective(oInvisible))
|
||||
{
|
||||
ai_HaveCreatureSpeak(oCreature, 20, ":21:47:7:");
|
||||
fDistance = GetDistanceBetween(oCreature, oInvisible);
|
||||
if(fDistance < AI_RANGE_LONG) ActionMoveAwayFromObject(oInvisible, TRUE, AI_RANGE_LONG);
|
||||
return TRUE;
|
||||
} */
|
||||
if(bMonster)
|
||||
{
|
||||
GetDistanceBetween(oCreature, oInvisible);
|
||||
fDistance = GetDistanceBetween(oCreature, oInvisible);
|
||||
fPerceptionDistance = GetLocalFloat(GetModule(), AI_RULE_PERCEPTION_DISTANCE);
|
||||
}
|
||||
else
|
||||
@@ -420,7 +432,7 @@ int ai_SearchForHiddenCreature(object oCreature, int bMonster, object oInvisible
|
||||
// We want to use the distance between the PC and target not us.
|
||||
object oMaster = GetMaster();
|
||||
if(oMaster != OBJECT_INVALID) fDistance = GetDistanceBetween(oMaster, oInvisible);
|
||||
else GetDistanceBetween(oCreature, oInvisible);
|
||||
else fDistance = GetDistanceBetween(oCreature, oInvisible);
|
||||
fPerceptionDistance = GetLocalFloat(oCreature, AI_ASSOC_PERCEPTION_DISTANCE);
|
||||
if(fPerceptionDistance == 0.0) fPerceptionDistance = 20.0;
|
||||
}
|
||||
@@ -533,6 +545,9 @@ int ai_MoralCheck(object oCreature)
|
||||
nRaceType == RACIAL_TYPE_UNDEAD ||
|
||||
nRaceType == RACIAL_TYPE_CONSTRUCT ||
|
||||
ai_GetIsCharacter(oCreature)) return FALSE;
|
||||
int nAssociateType = GetAssociateType(oCreature);
|
||||
//if(nAssociateType == ASSOCIATE_TYPE_FAMILIAR || nAssociateType == ASSOCIATE_TYPE_ANIMALCOMPANION ||
|
||||
// nAssociateType == ASSOCIATE_TYPE_SUMMONED) return FALSE;
|
||||
// Moral DC is AI_WOUNDED_MORAL_DC - The number of allies.
|
||||
// or AI_BLOODY_MORAL_DC - number of allies.
|
||||
int nDC;
|
||||
|
||||
@@ -52,6 +52,8 @@ void ai_OnRested(object oCreature);
|
||||
|
||||
// Increments/Decrements the following distance of associates.
|
||||
void ai_FollowIncrement(object oPC, object oAssociate, float fIncrement, string sAssociateType);
|
||||
// Increments/Decrements the delay when casting each auto buff spell.
|
||||
void ai_DelaySpellSpeed(object oPC, object oAssociate, float fIncrement, string sAssociateType);
|
||||
// Turns on/off Ranged combat for oAssociate.
|
||||
void ai_Ranged(object oPC, object oAssociate, string sAssociateType);
|
||||
// Turns on/off Ignore enemy associates for oAssociate.
|
||||
@@ -523,6 +525,24 @@ void ai_SelectAssociateCommand(object oCreature, object oCommander, int nCommand
|
||||
ai_FireHenchman (GetPCSpeaker(), oCreature);
|
||||
PlayVoiceChat (VOICE_CHAT_GOODBYE, oCreature);
|
||||
}
|
||||
else if(AI_PATROL_AHEAD_RADIAL_OPTION)
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_SCOUT_AHEAD))
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
ai_HaveCreatureSpeak(oCreature, 6, ":29:35:46:10");
|
||||
ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE);
|
||||
ai_SendMessages(GetName(oCreature) + " has stopped patrolling ahead.", AI_COLOR_YELLOW, oMaster);
|
||||
}
|
||||
else
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
ai_HaveCreatureSpeak(oCreature, 6, ":29:35:46:22:");
|
||||
ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, TRUE);
|
||||
ai_SendMessages(GetName(oCreature) + " is now patrolling ahead.", AI_COLOR_YELLOW, oMaster);
|
||||
ai_ScoutAhead(oCreature);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -773,7 +793,7 @@ void ai_AssociateEvaluateNewThreat(object oCreature, object oLastPerceived, stri
|
||||
if(sPerception == AI_I_SEE_AN_ENEMY || GetObjectSeen(oLastPerceived, oCreature))
|
||||
{
|
||||
// We are not in combat and we see the enemy so alert our allies!
|
||||
ai_HaveCreatureSpeak(oCreature, 5, ":0:1:2:3:6:");
|
||||
ai_HaveCreatureSpeak(oCreature, 10, ":0:1:2:3:6:");
|
||||
SetLocalObject (oCreature, AI_MY_TARGET, oLastPerceived);
|
||||
SpeakString(sPerception, TALKVOLUME_SILENT_TALK);
|
||||
ai_StartAssociateCombat(oCreature);
|
||||
@@ -836,7 +856,7 @@ void ai_MonsterEvaluateNewThreat(object oCreature, object oLastPerceived, string
|
||||
if(d100() < 34)
|
||||
{
|
||||
// We are not in combat so alert our allies!
|
||||
ai_HaveCreatureSpeak(oCreature, 5, ":0:1:2:3:6:");
|
||||
ai_HaveCreatureSpeak(oCreature, 10, ":0:1:2:3:6:");
|
||||
}
|
||||
SetLocalObject(oCreature, AI_MY_TARGET, oLastPerceived);
|
||||
SpeakString(AI_I_SEE_AN_ENEMY, TALKVOLUME_SILENT_TALK);
|
||||
@@ -923,6 +943,23 @@ void ai_FollowIncrement(object oPC, object oAssociate, float fIncrement, string
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_follow_target_tooltip", " " + GetName(oAssociate) + " following " + sTarget + " [" + sRange + " meters]");
|
||||
}
|
||||
}
|
||||
void ai_DelaySpellSpeed(object oPC, object oAssociate, float fIncrement, string sAssociateType)
|
||||
{
|
||||
float fAdjustment = GetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING) + fIncrement;
|
||||
if(fAdjustment > 6.0) fAdjustment = 6.0;
|
||||
else if(fAdjustment < 0.1) fAdjustment = 0.1;
|
||||
SetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING, fAdjustment);
|
||||
json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata");
|
||||
jAIData = JsonArraySet(jAIData, 11, JsonFloat(fAdjustment));
|
||||
ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData);
|
||||
string sDelay = FloatToString(fAdjustment, 0, 1);
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI,
|
||||
"btn_buff_long_tooltip", " Buff the party with long duration spells. Cast speed [" + sDelay + "]");
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI,
|
||||
"btn_buff_short_tooltip", " Buff the party with short duration spells. Cast speed [" + sDelay + "]");
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI,
|
||||
"btn_buff_all_tooltip", " Buff the party with all spells. Cast speed [" + sDelay + "]");
|
||||
}
|
||||
void ai_Ranged(object oPC, object oAssociate, string sAssociateType)
|
||||
{
|
||||
//ai_ClearCreatureActions();
|
||||
|
||||
@@ -574,7 +574,7 @@ int ai_GetRacialTypeCount(object oCreature, int nRacial_Type, float fDistance =
|
||||
object ai_GetLowestCRAttackerOnMaster(object oCreature)
|
||||
{
|
||||
object oTarget = OBJECT_INVALID, oMaster = GetMaster(oCreature);
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "419", "Checking for weakest attacker on " + GetName(oMaster));
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "577", "Checking for weakest attacker on " + GetName(oMaster));
|
||||
int nEnemyCombatRating, nWeakestCombatRating, nCntr = 1;
|
||||
float fNearest = AI_RANGE_MELEE + 1.0f;
|
||||
// Get the weakest opponent in melee with our master.
|
||||
@@ -583,7 +583,7 @@ object ai_GetLowestCRAttackerOnMaster(object oCreature)
|
||||
while (oEnemy != OBJECT_INVALID && fDistance <= AI_RANGE_MELEE)
|
||||
{
|
||||
nEnemyCombatRating = ai_GetMyCombatRating(oEnemy);
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "428", GetName(oEnemy) + " nECR: " + IntToString(nEnemyCombatRating));
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "586", GetName(oEnemy) + " nECR: " + IntToString(nEnemyCombatRating));
|
||||
if (nEnemyCombatRating < nWeakestCombatRating ||
|
||||
nEnemyCombatRating == nWeakestCombatRating && fDistance < fNearest)
|
||||
{
|
||||
@@ -594,7 +594,13 @@ object ai_GetLowestCRAttackerOnMaster(object oCreature)
|
||||
oEnemy = ai_GetNearestEnemy(oMaster, ++nCntr, 7, 7);
|
||||
}
|
||||
// No targets in melee with our master, lets see if there is a ranged attacker.
|
||||
if (oTarget == OBJECT_INVALID) oTarget = GetLastHostileActor(oMaster);
|
||||
if (oTarget == OBJECT_INVALID)
|
||||
{
|
||||
oTarget = GetLastHostileActor(oMaster);
|
||||
// Sometimes things happen and our own associates may hurt the player too!
|
||||
if(ai_GetTopMaster(oTarget) == oMaster) oTarget = OBJECT_INVALID;
|
||||
}
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "598", "Attacking master: " + GetName(oTarget));
|
||||
return oTarget;
|
||||
}
|
||||
|
||||
@@ -1091,7 +1097,101 @@ struct stTarget ai_CheckForLowestValueAllTarget(object oCreature, struct stTarge
|
||||
}
|
||||
return sTarget;
|
||||
}
|
||||
|
||||
struct stTarget ai_CheckForNearestPhysicalTarget(object oCreature, struct stTarget sTarget, int nIndex, string sIndex)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "969", "Getting nearest physical index: " + sIndex +
|
||||
" fRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) +
|
||||
" fNearestRange: " + FloatToString(sTarget.fNearestRange, 0, 2) +
|
||||
" fNearestSecondaryRange: " + FloatToString(sTarget.fNearestSecondaryRange, 0, 2) +
|
||||
" Weapon Effective: " + IntToString(GetIsWeaponEffective(sTarget.oTarget)));
|
||||
// Lets put any disabled targets and associates if set in a secondary group.
|
||||
if(GetLocalInt(oCreature, sTarget.sTargetType + "_DISABLED" + sIndex) ||
|
||||
!GetIsWeaponEffective(sTarget.oTarget) ||
|
||||
(ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && GetAssociateType(sTarget.oTarget)))
|
||||
{
|
||||
if(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestSecondaryRange)
|
||||
{
|
||||
sTarget.fNearestSecondaryRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex);
|
||||
sTarget.nSecondaryIndex = nIndex;
|
||||
}
|
||||
}
|
||||
else if(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestRange)
|
||||
{
|
||||
sTarget.fNearestRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex);
|
||||
sTarget.nIndex = nIndex;
|
||||
}
|
||||
return sTarget;
|
||||
}
|
||||
struct stTarget ai_CheckForLowestValuePhysicalTarget(object oCreature, struct stTarget sTarget, int nIndex, string sIndex)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1126", "Getting lowest value physcial index: " + sIndex +
|
||||
" fRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) +
|
||||
" fNearestRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) +
|
||||
" fNearestSecondaryRange: " + FloatToString(sTarget.fNearestSecondaryRange, 0, 2) +
|
||||
" sTarget.nValue: " + IntToString(sTarget.nValue) +
|
||||
" sTarget.nBestValue: " + IntToString(sTarget.nBestValue) +
|
||||
" sTarget.nBestSecondaryValue: " + IntToString(sTarget.nBestSecondaryValue) +
|
||||
" Weapon Effective: " + IntToString(GetIsWeaponEffective(sTarget.oTarget)));
|
||||
// Lets put any disabled targets and associates if set in a secondary group.
|
||||
if(GetLocalInt(oCreature, sTarget.sTargetType + "_DISABLED" + sIndex) ||
|
||||
!GetIsWeaponEffective(sTarget.oTarget) ||
|
||||
(ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && GetAssociateType(sTarget.oTarget)))
|
||||
{
|
||||
if(sTarget.nValue < sTarget.nBestSecondaryValue ||
|
||||
(sTarget.nValue == sTarget.nBestSecondaryValue &&
|
||||
GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestSecondaryRange))
|
||||
{
|
||||
sTarget.fNearestSecondaryRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex);
|
||||
sTarget.nBestSecondaryValue = sTarget.nValue;
|
||||
sTarget.nSecondaryIndex = nIndex;
|
||||
}
|
||||
}
|
||||
// Has less value or equal value and is closer.
|
||||
else if(sTarget.nValue < sTarget.nBestValue ||
|
||||
(sTarget.nBestValue == sTarget.nValue &&
|
||||
GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestRange))
|
||||
{
|
||||
sTarget.fNearestRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex);
|
||||
sTarget.nBestValue = sTarget.nValue;
|
||||
sTarget.nIndex = nIndex;
|
||||
}
|
||||
return sTarget;
|
||||
}
|
||||
struct stTarget ai_CheckForHighestValuePhysicalTarget(object oCreature, struct stTarget sTarget, int nIndex, string sIndex)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1025", "Getting highest value physical index: " + sIndex +
|
||||
" fRange: " + FloatToString(GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex), 0, 2) +
|
||||
" fNearestRange: " + FloatToString(sTarget.fNearestRange, 0, 2) +
|
||||
" fNearestSecondaryRange: " + FloatToString(sTarget.fNearestSecondaryRange, 0, 2) +
|
||||
" sTarget.nValue: " + IntToString(sTarget.nValue) +
|
||||
" sTarget.nBestValue: " + IntToString(sTarget.nBestValue) +
|
||||
" sTarget.nBestSecondaryValue: " + IntToString(sTarget.nBestSecondaryValue) +
|
||||
" Weapon Effective: " + IntToString(GetIsWeaponEffective(sTarget.oTarget)));
|
||||
// Lets put any disabled targets and associates if set in a secondary group.
|
||||
if(GetLocalInt(oCreature, sTarget.sTargetType + "_DISABLED" + sIndex) ||
|
||||
!GetIsWeaponEffective(sTarget.oTarget) ||
|
||||
(ai_GetAIMode(oCreature, AI_MODE_IGNORE_ASSOCIATES) && GetAssociateType(sTarget.oTarget)))
|
||||
{
|
||||
if(sTarget.nValue > sTarget.nBestSecondaryValue ||
|
||||
(sTarget.nValue == sTarget.nBestSecondaryValue &&
|
||||
GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestSecondaryRange))
|
||||
{
|
||||
sTarget.fNearestSecondaryRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex);
|
||||
sTarget.nBestSecondaryValue = sTarget.nValue;
|
||||
sTarget.nSecondaryIndex = nIndex;
|
||||
}
|
||||
}
|
||||
// Has less value or equal value and is closer.
|
||||
else if(sTarget.nValue > sTarget.nBestValue ||
|
||||
(sTarget.nBestValue == sTarget.nValue &&
|
||||
GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex) < sTarget.fNearestRange))
|
||||
{
|
||||
sTarget.fNearestRange = GetLocalFloat(oCreature, sTarget.sTargetType + "_RANGE" + sIndex);
|
||||
sTarget.nBestValue = sTarget.nValue;
|
||||
sTarget.nIndex = nIndex;
|
||||
}
|
||||
return sTarget;
|
||||
}
|
||||
//******************************************************************************
|
||||
//************ GET INDEX/TARGETs USING COMBAT STATE FUNCTIONS ******************
|
||||
//******************************************************************************
|
||||
@@ -1361,21 +1461,19 @@ int ai_GetNearestPhysicalIndex(object oCreature, float fMaxRange = AI_RANGE_PERC
|
||||
sTarget.oTarget = GetLocalObject(oCreature, sTargetType + sCounter);
|
||||
while(sTarget.oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1459", "Getting the nearest physical index: " +
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1464", "Getting the nearest physical index: " +
|
||||
sCounter + " " + GetName(sTarget.oTarget) +
|
||||
" Seen: " + IntToString(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter)) +
|
||||
" GetIsDead: " + IntToString(GetIsDead(sTarget.oTarget)));
|
||||
if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) &&
|
||||
!GetIsDead(sTarget.oTarget))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1466", "bAlwaysAtk: " + IntToString(bAlwaysAtk) +
|
||||
" Weapon Effective: " + IntToString(GetIsWeaponEffective(sTarget.oTarget)));
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1471", "bAlwaysAtk: " + IntToString(bAlwaysAtk));
|
||||
if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) &&
|
||||
GetIsWeaponEffective(sTarget.oTarget) &&
|
||||
ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) &&
|
||||
ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget))
|
||||
{
|
||||
sTarget = ai_CheckForNearestTarget(oCreature, sTarget, nCounter, sCounter);
|
||||
sTarget = ai_CheckForNearestPhysicalTarget(oCreature, sTarget, nCounter, sCounter);
|
||||
}
|
||||
}
|
||||
sCounter = IntToString(++nCounter);
|
||||
@@ -1383,7 +1481,7 @@ int ai_GetNearestPhysicalIndex(object oCreature, float fMaxRange = AI_RANGE_PERC
|
||||
}
|
||||
// If we do not have a normal target then use our best secondary target.
|
||||
if(sTarget.nIndex == 0 && sTarget.nSecondaryIndex != 0) sTarget.nIndex = sTarget.nSecondaryIndex;
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1479", "Found nearest [" + sTargetType + "] Physical Index: " + IntToString(sTarget.nIndex));
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1484", "Found nearest [" + sTargetType + "] Physical Index: " + IntToString(sTarget.nIndex));
|
||||
return sTarget.nIndex;
|
||||
}
|
||||
object ai_GetNearestPhysicalTarget(object oCreature, float fMaxRange = AI_RANGE_PERCEPTION, string sTargetType = AI_ENEMY, int bAlwaysAtk = TRUE)
|
||||
@@ -1412,15 +1510,13 @@ int ai_GetLowestCRPhysicalIndex(object oCreature, float fMaxRange = AI_RANGE_PER
|
||||
if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) &&
|
||||
!GetIsDead(sTarget.oTarget))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1508", "bAlwaysAtk: " + IntToString(bAlwaysAtk) +
|
||||
" Weapon Effective: " + IntToString(GetIsWeaponEffective(sTarget.oTarget)));
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1508", "bAlwaysAtk: " + IntToString(bAlwaysAtk));
|
||||
if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) &&
|
||||
GetIsWeaponEffective(sTarget.oTarget) &&
|
||||
ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) &&
|
||||
ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget))
|
||||
{
|
||||
sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter);
|
||||
sTarget = ai_CheckForLowestValueTarget(oCreature, sTarget, nCounter, sCounter);
|
||||
sTarget = ai_CheckForLowestValuePhysicalTarget(oCreature, sTarget, nCounter, sCounter);
|
||||
}
|
||||
}
|
||||
sCounter = IntToString(++nCounter);
|
||||
@@ -1457,15 +1553,13 @@ int ai_GetHighestCRPhysicalIndex(object oCreature, float fMaxRange = AI_RANGE_PE
|
||||
if(GetLocalInt(oCreature, sTargetType + "_PERCEIVED" + sCounter) &&
|
||||
!GetIsDead(sTarget.oTarget))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1551", "bAlwaysAtk: " + IntToString(bAlwaysAtk) +
|
||||
" Weapon Effective: " + IntToString(GetIsWeaponEffective(sTarget.oTarget)));
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "1551", "bAlwaysAtk: " + IntToString(bAlwaysAtk));
|
||||
if((bAlwaysAtk || !ai_IsStrongerThanMe(oCreature, nCounter)) &&
|
||||
GetIsWeaponEffective(sTarget.oTarget) &&
|
||||
ai_TargetIsInRangeofCreature(oCreature, sTargetType, sCounter, fMaxRange) &&
|
||||
ai_TargetIsInRangeofMaster(oCreature, sTarget.oTarget))
|
||||
{
|
||||
sTarget.nValue = GetLocalInt(oCreature, sTargetType + "_COMBAT" + sCounter);
|
||||
sTarget = ai_CheckForHighestValueTarget(oCreature, sTarget, nCounter, sCounter);
|
||||
sTarget = ai_CheckForHighestValuePhysicalTarget(oCreature, sTarget, nCounter, sCounter);
|
||||
}
|
||||
}
|
||||
sCounter = IntToString(++nCounter);
|
||||
@@ -3505,7 +3599,7 @@ int ai_IsInADangerousAOE(object oCreature, float fMaxRange = AI_RANGE_BATTLEFIEL
|
||||
ActionMoveToLocation(lLocation, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
else if(bDangerous) return TRUE;
|
||||
else return bDangerous;
|
||||
return FALSE;
|
||||
}
|
||||
int ai_GetIsHidden(object oHidden)
|
||||
@@ -3808,7 +3902,44 @@ int ai_CheckRangedCombatPosition(object oCreature, object oTarget, int nAction)
|
||||
float fDistance = GetDistanceBetween(oCreature, oNearestEnemy);
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "3337", "oNearestEnemy: " + GetName(oNearestEnemy) +
|
||||
" fDistance: " + FloatToString(fDistance, 0, 2));
|
||||
// If we have sneak attack then we want to be within 30'.
|
||||
// If we have Point blank shot then we want to be within 15' [4 meters].
|
||||
if(GetHasFeat(FEAT_POINT_BLANK_SHOT, oCreature))
|
||||
{
|
||||
if(fDistance > AI_RANGE_MELEE)
|
||||
{
|
||||
// We check this because if the enemy is moving or has not
|
||||
// started acting then we don't want to move up on them as they
|
||||
// might move towards us. Just attack! Only sneak attack if they are busy.
|
||||
int nAction = GetCurrentAction(oNearestEnemy);
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "3353", GetName(oNearestEnemy) + " current action: " + IntToString(nAction));
|
||||
if(nAction == ACTION_MOVETOPOINT ||
|
||||
nAction == ACTION_INVALID ||
|
||||
nAction == ACTION_RANDOMWALK) return FALSE;
|
||||
// If they are attacking make sure it is in melee?
|
||||
// If not then don't move since they might be moving toward us.
|
||||
if(nAction == ACTION_ATTACKOBJECT)
|
||||
{
|
||||
if(!ai_GetNumOfEnemiesInRange(oNearestEnemy)) return FALSE;
|
||||
}
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "3355", GetName(oCreature) + " is moving closer [4.0] to " +
|
||||
GetName(oNearestEnemy) + " to use Point blank shot with a ranged weapon.");
|
||||
ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE);
|
||||
ActionMoveToObject(oNearestEnemy, TRUE, AI_RANGE_CLOSE);
|
||||
ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if(fDistance < AI_RANGE_LONG)
|
||||
{
|
||||
// Lets move back a little, too far and we miss attacks!
|
||||
if(AI_DEBUG) ai_Debug("0i_combat", "3374", GetName(oCreature) + " is moving away from " +
|
||||
GetName(oNearestEnemy) + "[2.0] to use a ranged weapon.");
|
||||
ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE);
|
||||
ActionMoveAwayFromObject(oNearestEnemy, TRUE, 2.0);
|
||||
ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature));
|
||||
return TRUE;
|
||||
}
|
||||
// If we have sneak attack then we want to be within 30' [9 meters].
|
||||
if(GetHasFeat(FEAT_SNEAK_ATTACK, oCreature))
|
||||
{
|
||||
if(fDistance > AI_RANGE_CLOSE)
|
||||
@@ -3873,7 +4004,7 @@ int ai_CheckRangedCombatPosition(object oCreature, object oTarget, int nAction)
|
||||
ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
int ai_CheckMeleeCombatPosition(object oCreature, object oTarget, int nAction, int nBaseItemType = 0)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
Changes to any constants will not take effect until the scripts are recompiled.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const string PHILOS_VERSION = "Philos' Enhancing Player System (PEPS) version:08.31.25";
|
||||
const string PHILOS_VERSION = "Philos' Enhancing Player System (PEPS) version:11.16.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
|
||||
@@ -35,14 +35,14 @@ const int AI_MONSTER_HEAL_OUT_COMBAT_CHANCE = 70;
|
||||
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 to buff with all spells before combat starts. VERY DIFFICULT!
|
||||
const int AI_FULL_BUFF = FALSE;
|
||||
// Allows monsters cast summons spells when prebuffing.
|
||||
const int AI_PRESUMMONS = TRUE;
|
||||
// Allows monsters to use tactical AI scripts such as ambush, flanker, ranged.
|
||||
@@ -111,8 +111,13 @@ const int AI_SCOUT_AHEAD_ON = TRUE;
|
||||
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.
|
||||
// Allows players to take any henchman that is standing around.
|
||||
const int AI_ALLOW_TAKING_HENCHMAN = FALSE;
|
||||
// Allows players to remove a henchman through PEPS.
|
||||
const int AI_REMOVE_HENCHMAN_ON = FALSE;
|
||||
// Allows players to toggle patrolling ahead via the radial menu for remove henchman.
|
||||
// Used on my server as a way to toggle patrolling ahead via the radial menu.
|
||||
const int AI_PATROL_AHEAD_RADIAL_OPTION = FALSE;
|
||||
//***************************** Health Constants *****************************
|
||||
// % of health for when a creature is considered wounded.
|
||||
const int AI_HEALTH_WOUNDED = 50;
|
||||
@@ -162,7 +167,7 @@ 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;
|
||||
const int AI_MAX_HENCHMAN = 30;
|
||||
// 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.
|
||||
@@ -240,6 +245,8 @@ 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";
|
||||
// Constants used in combat to keep track of a creatures last action time.
|
||||
const string sLastActionTimeVarname = "AI_LAST_ACTION_TIME";
|
||||
const int AI_LAST_ACTION_CAST_SPELL = -1;
|
||||
const int AI_LAST_ACTION_NONE = -2;
|
||||
const int AI_LAST_ACTION_MELEE_ATK = -3;
|
||||
@@ -527,6 +534,8 @@ const string AI_ASSOCIATE_PERCEPTION = "AI_PERCEPTION_RANGE";
|
||||
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 delay for casting buff spells.
|
||||
const string AI_DELAY_BUFF_CASTING = "AI_DELAY_BUFF_CASTING";
|
||||
// Variable that holds the Spell widgets json data.
|
||||
const string AI_SPELLS_WIDGET = "AI_SPELLS_WIDGET";
|
||||
// The number of Buff Groups
|
||||
@@ -554,6 +563,8 @@ const string AI_PC_LOCKED_TARGET = "AI_PC_LOCKED_TARGET";
|
||||
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_";
|
||||
// Variables keeps track of the maximum level for the talent level.
|
||||
const string AI_MAX_LEVEL = "AI_MAX_LEVEL_";
|
||||
// Backward compatability constants.
|
||||
const int X2_EVENT_CONCENTRATION_BROKEN = 12400;
|
||||
// Variable set on the module if the module is using PRC.
|
||||
@@ -597,6 +608,8 @@ const string AI_RULE_DEBUG_CREATURE = "AI_RULE_DEBUG_CREATURE";
|
||||
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 prebuff with all defensive spells before combat starts.
|
||||
const string AI_RULE_FULL_BUFF_MONSTERS = "AI_RULE_FULL_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.
|
||||
|
||||
@@ -34,6 +34,9 @@ int ai_GetIsDungeonMaster(object oCreature);
|
||||
// Returns the Player of oAssociate even if oAssociate is the player.
|
||||
// If there is no player associated with oAssociate then it returns OBJECT_INVALID.
|
||||
object ai_GetPlayerMaster(object oAssociate);
|
||||
// Returns the top master of oAssociate, for example a henchmen summons a bat,
|
||||
// this will return the henchman's player.
|
||||
object ai_GetTopMaster(object oAssociate);
|
||||
// Returns the percentage of hit points oCreature has left.
|
||||
int ai_GetPercHPLoss(object oCreature);
|
||||
// Returns a rolled result from sDice string.
|
||||
@@ -131,6 +134,9 @@ void ai_SetAIRules()
|
||||
// Allows monsters to prebuff before combat starts.
|
||||
SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, AI_PREBUFF);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_BUFF_MONSTERS, JsonInt(AI_PREBUFF));
|
||||
// Allows monsters to prebuff with all spells before combat starts.
|
||||
SetLocalInt(oModule, AI_RULE_FULL_BUFF_MONSTERS, AI_FULL_BUFF);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_FULL_BUFF_MONSTERS, JsonInt(AI_FULL_BUFF));
|
||||
// Allows monsters cast summons spells when prebuffing.
|
||||
SetLocalInt(oModule, AI_RULE_PRESUMMON, AI_PRESUMMONS);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_PRESUMMON, JsonInt(AI_PRESUMMONS));
|
||||
@@ -217,6 +223,9 @@ void ai_SetAIRules()
|
||||
// Allows monsters to prebuff before combat starts.
|
||||
bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_BUFF_MONSTERS));
|
||||
SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, bValue);
|
||||
// Allows monsters to buff with all spells before combat starts.
|
||||
bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_FULL_BUFF_MONSTERS));
|
||||
SetLocalInt(oModule, AI_RULE_FULL_BUFF_MONSTERS, bValue);
|
||||
// Allows monsters cast summons spells when prebuffing.
|
||||
bValue = JsonGetInt(JsonObjectGet(jRules, AI_RULE_PRESUMMON));
|
||||
SetLocalInt(oModule, AI_RULE_PRESUMMON, bValue);
|
||||
@@ -328,6 +337,16 @@ object ai_GetPlayerMaster(object oAssociate)
|
||||
if(ai_GetIsCharacter(oMaster)) return oMaster;
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
object ai_GetTopMaster(object oAssociate)
|
||||
{
|
||||
object oMaster = GetMaster(oAssociate);
|
||||
while(oMaster != OBJECT_INVALID)
|
||||
{
|
||||
if(GetMaster(oMaster) == OBJECT_INVALID) break;
|
||||
oMaster = GetMaster(oMaster);
|
||||
}
|
||||
return oMaster;
|
||||
}
|
||||
int ai_GetPercHPLoss(object oCreature)
|
||||
{
|
||||
int nHP = GetCurrentHitPoints(oCreature);
|
||||
@@ -874,6 +893,8 @@ void ai_SetupAIData(object oPlayer, object oAssociate, string sAssociateType)
|
||||
SetLocalFloat(oAssociate, AI_OPEN_DOORS_RANGE, 20.0);
|
||||
json jSpells = JsonArray();
|
||||
jAIData = JsonArrayInsert(jAIData, jSpells); // 10 - Castable spells.
|
||||
jAIData = JsonArrayInsert(jAIData, JsonFloat(0.1)); // 11 - Delay for casting buff spells.
|
||||
SetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING, 0.1);
|
||||
ai_SetAssociateDbJson(oPlayer, sAssociateType, "aidata", jAIData, AI_TABLE);
|
||||
}
|
||||
void ai_SetupLootFilters(object oPlayer, object oAssociate, string sAssociateType)
|
||||
@@ -985,6 +1006,8 @@ void ai_RestoreDatabase(object oPlayer, object oAssociate, string sAssociateType
|
||||
SetLocalJson(oPlayer, AI_SPELLS_WIDGET, jValue);
|
||||
}
|
||||
jAIData = JsonArrayInsert(jAIData, jValue);
|
||||
fValue = GetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING);
|
||||
jAIData = JsonArrayInsert(jAIData, JsonFloat(fValue));
|
||||
ai_SetAssociateDbJson(oPlayer, sAssociateType, "aidata", jAIData);
|
||||
// ********** LootFilters **********
|
||||
json jLootFilters = JsonArray();
|
||||
@@ -1086,6 +1109,14 @@ void ai_CheckAssociateData(object oPlayer, object oAssociate, string sAssociateT
|
||||
ai_SetAssociateDbJson(oPlayer, sAssociateType, "aidata", jAIData);
|
||||
SetLocalJson(oPlayer, AI_SPELLS_WIDGET, jSpellsWidget);
|
||||
}
|
||||
json jSpellDelay = JsonArrayGet(jAIData, 11);
|
||||
if(JsonGetType(jSpellDelay) == JSON_TYPE_NULL)
|
||||
{
|
||||
jAIData = JsonArrayInsert(jAIData, JsonFloat(0.1));
|
||||
ai_SetAssociateDbJson(oPlayer, sAssociateType, "aidata", jAIData);
|
||||
SetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING, 0.1);
|
||||
}
|
||||
else SetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING, JsonGetFloat(jSpellDelay));
|
||||
}
|
||||
// ********** LootFilters **********
|
||||
json jLootFilters = ai_GetAssociateDbJson(oPlayer, sAssociateType, "lootfilters");
|
||||
|
||||
@@ -410,7 +410,8 @@ void ai_CreateAIMainNUI(object oPC)
|
||||
jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_perception_distance", 2, FALSE, 35.0f, 20.0f, "txt_perception_distance_tooltip");
|
||||
jGroupRow = CreateLabel(jGroupRow, "meters is the distance a monster can respond to allies.", "lbl_perception_distance", 411.0f, 20.0f, NUI_HALIGN_LEFT, 0, 0.0, "txt_perception_distance_tooltip");
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
jGroupRow = CreateCheckBox(JsonArray(), " Monsters can prebuff before combat starts.", "chbx_buff_monsters", 450.0, 20.0);
|
||||
jGroupRow = CreateCheckBox(JsonArray(), " Monsters buff before combat starts.", "chbx_buff_monsters", 275.0, 20.0, "chbx_buff_monsters_tooltip");
|
||||
jGroupRow = CreateCheckBox(jGroupRow, " Will use all buff spells!", "chbx_full_buff", 210.0, 20.0, "chbx_full_buff_tooltip");
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
jGroupRow = CreateCheckBox(JsonArray(), " Monsters can use summons before combat starts.", "chbx_buff_summons", 450.0, 20.0);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
@@ -454,7 +455,7 @@ void ai_CreateAIMainNUI(object oPC)
|
||||
if(GetStringRight(sName, 1) == "s") sName = sName + "'";
|
||||
else sName = sName + "'s";
|
||||
int nToken = SetWindow(oPC, jLayout, AI_MAIN_NUI, sName + " PEPS Main Menu",
|
||||
fX, fY, 534.0f, fHeight, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui");
|
||||
fX, fY, 554.0f, fHeight, FALSE, FALSE, TRUE, FALSE, TRUE, "0e_nui");
|
||||
// Save the associate to the nui for use in 0e_nui
|
||||
json jData = JsonArray();
|
||||
jData = JsonArrayInsert(jData, JsonString(ObjectToString(oPC)));
|
||||
@@ -537,9 +538,15 @@ void ai_CreateAIMainNUI(object oPC)
|
||||
NuiSetBind(oPC, nToken, "txt_ai_difficulty", JsonString(IntToString(GetLocalInt(oModule, AI_RULE_AI_DIFFICULTY))));
|
||||
NuiSetBindWatch(oPC, nToken, "txt_ai_difficulty", TRUE);
|
||||
NuiSetBind(oPC, nToken, "txt_ai_difficulty_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_monsters_check", JsonBool(GetLocalInt(oModule, AI_RULE_BUFF_MONSTERS)));
|
||||
int bMonsterBuff = GetLocalInt(oModule, AI_RULE_BUFF_MONSTERS);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_monsters_check", JsonBool(bMonsterBuff));
|
||||
NuiSetBindWatch(oPC, nToken, "chbx_buff_monsters_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_monsters_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_monsters_tooltip", JsonString(" Monsters will cast all longer duration buff spells just before combat starts."));
|
||||
NuiSetBind(oPC, nToken, "chbx_full_buff_check", JsonBool(GetLocalInt(oModule, AI_RULE_FULL_BUFF_MONSTERS)));
|
||||
NuiSetBindWatch(oPC, nToken, "chbx_full_buff_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_full_buff_event", JsonBool(bMonsterBuff));
|
||||
NuiSetBind(oPC, nToken, "chbx_full_buff_tooltip", JsonString(" Monsters will cast all buff spells just before combat starts! VERY DIFFICULTY!"));
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_summons_check", JsonBool(GetLocalInt(oModule, AI_RULE_PRESUMMON)));
|
||||
NuiSetBindWatch(oPC, nToken, "chbx_buff_summons_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_summons_event", JsonBool(TRUE));
|
||||
@@ -595,6 +602,7 @@ void ai_CreateAIMainNUI(object oPC)
|
||||
NuiSetBind(oPC, nToken, "txt_inc_enc_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_inc_hp", JsonString(IntToString(GetLocalInt(oModule, AI_INCREASE_MONSTERS_HP))));
|
||||
NuiSetBindWatch(oPC, nToken, "txt_inc_hp", TRUE);
|
||||
NuiSetBind(oPC, nToken, "txt_inc_hp_tooltip", JsonString(" Will increase ALL monsters hitpoints by the%. Upto 500% or 6 times the normal health!"));
|
||||
NuiSetBind(oPC, nToken, "txt_inc_hp_event", JsonBool(TRUE));
|
||||
}
|
||||
if(nMonsterAI || nAssociateAI)
|
||||
@@ -1272,21 +1280,24 @@ void ai_CreateAssociateCommandNUI(object oPC, object oAssociate)
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_buff_short_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_short_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_buff_short_event", JsonBool (TRUE));
|
||||
float fDelay = GetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING);
|
||||
if(fDelay < 0.1) fDelay = 0.1;
|
||||
string sDelay = FloatToString(fDelay, 0, 1);
|
||||
NuiSetBind (oPC, nToken, "btn_buff_short_tooltip", JsonString (
|
||||
" Buff the party with short duration spells"));
|
||||
" Buff the party with short duration spells. Cast speed [" + sDelay + "]"));
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_long_check", JsonBool (bBuffLong));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_buff_long_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_long_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_buff_long_event", JsonBool (TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_buff_long_tooltip", JsonString (
|
||||
" Buff the party with long duration spells"));
|
||||
" Buff the party with long duration spells. Cast speed [" + sDelay + "]"));
|
||||
// Row 11
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_all_check", JsonBool (bBuffAll));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_buff_all_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_all_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_buff_all_event", JsonBool (TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_buff_all_tooltip", JsonString (
|
||||
" Buff the party with all our defensive spells"));
|
||||
" Buff the party with all spells. Cast speed [" + sDelay + "]"));
|
||||
if(!bIsPC && ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS) == "")
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_rest_check", JsonBool (bBuffRest));
|
||||
@@ -1466,7 +1477,7 @@ void ai_CreateAssociateAINUI(object oPC, object oAssociate)
|
||||
fHeight += 28.0;
|
||||
}
|
||||
// Row 3 ******************************************************************* 500 / 101
|
||||
bRight = !ai_GetDMAIAccessButton(BTN_AI_FOR_PC);
|
||||
bRight = TRUE;//!ai_GetDMAIAccessButton(BTN_AI_FOR_PC);
|
||||
bLeft = !ai_GetDMAIAccessButton(BTN_AI_REDUCE_SPEECH);
|
||||
if(bRight || bLeft)
|
||||
{
|
||||
@@ -1828,7 +1839,7 @@ void ai_CreateAssociateAINUI(object oPC, object oAssociate)
|
||||
NuiSetBind(oPC, nToken, "btn_loot_filter", JsonInt(TRUE));
|
||||
// Row 3
|
||||
// Only activate ai on/off if this is for the pc.
|
||||
if(bIsPC && ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS) == "")
|
||||
if(bIsPC && TRUE)//ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS) == "")
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "chbx_ai_check", JsonBool(bAI));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_ai_check", TRUE);
|
||||
@@ -2060,7 +2071,14 @@ void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int
|
||||
// Set event watches for save window location.
|
||||
NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE);
|
||||
// Set the buttons to show events.
|
||||
NuiSetBind(oPC, nToken, "btn_open_main_image", JsonString(GetPortraitResRef(oAssociate) + "s"));
|
||||
string sPortrait = GetPortraitResRef(oAssociate);
|
||||
string sSize;
|
||||
if(ResManGetAliasFor(sPortrait + "s", RESTYPE_TGA) != "") sSize = "s";
|
||||
else if(ResManGetAliasFor(sPortrait + "m", RESTYPE_TGA) != "") sSize = "m";
|
||||
else if(ResManGetAliasFor(sPortrait + "l", RESTYPE_TGA)!= "") sSize = "l";
|
||||
else if(ResManGetAliasFor(sPortrait + "h", RESTYPE_TGA)!= "") sSize = "h";
|
||||
else sSize = "m";
|
||||
NuiSetBind(oPC, nToken, "btn_open_main_image", JsonString(sPortrait + sSize));
|
||||
NuiSetBind(oPC, nToken, "btn_open_main_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_open_main_tooltip", JsonString(" " + sName + " widget menu"));
|
||||
if(ai_GetWidgetButton(oPC, BTN_ASSOC_WIDGETS_OFF, oAssociate, sAssociateType))
|
||||
@@ -2215,17 +2233,29 @@ void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int
|
||||
if(ai_GetWidgetButton(oPC, BTN_BUFF_SHORT, oAssociate, sAssociateType))
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "btn_buff_short_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_buff_short_tooltip", JsonString(" Buff the party with short duration spells"));
|
||||
float fDelay = GetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING);
|
||||
if(fDelay < 0.1) fDelay = 0.1;
|
||||
string sDelay = FloatToString(fDelay, 0, 1);
|
||||
NuiSetBind (oPC, nToken, "btn_buff_short_tooltip", JsonString(
|
||||
" Buff the party with short duration spells. Cast speed [" + sDelay + "]"));
|
||||
}
|
||||
if(ai_GetWidgetButton(oPC, BTN_BUFF_LONG, oAssociate, sAssociateType))
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "btn_buff_long_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_buff_long_tooltip", JsonString(" Buff the party with long duration spells"));
|
||||
float fDelay = GetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING);
|
||||
if(fDelay < 0.1) fDelay = 0.1;
|
||||
string sDelay = FloatToString(fDelay, 0, 1);
|
||||
NuiSetBind (oPC, nToken, "btn_buff_long_tooltip", JsonString(
|
||||
" Buff the party with long duration spells. Cast speed [" + sDelay + "]"));
|
||||
}
|
||||
if(ai_GetWidgetButton(oPC, BTN_BUFF_ALL, oAssociate, sAssociateType))
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "btn_buff_all_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_buff_all_tooltip", JsonString(" Buff the party with all our defensive spells"));
|
||||
float fDelay = GetLocalFloat(oAssociate, AI_DELAY_BUFF_CASTING);
|
||||
if(fDelay < 0.1) fDelay = 0.1;
|
||||
string sDelay = FloatToString(fDelay, 0, 1);
|
||||
NuiSetBind (oPC, nToken, "btn_buff_all_tooltip", JsonString(
|
||||
" Buff the party with all spells. Cast speed [" + sDelay + "]"));
|
||||
}
|
||||
if(ai_GetWidgetButton(oPC, BTN_CMD_JUMP_TO, oAssociate, sAssociateType))
|
||||
{
|
||||
@@ -2488,7 +2518,7 @@ void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int
|
||||
object oItem;
|
||||
if(JsonGetType(jWidget) != JSON_TYPE_NULL)
|
||||
{
|
||||
int nLevel, nSpell, nIndex, nClass, nMetaMagic, nDomain, nSubSpell, nFeat, nSAIndex;
|
||||
int nLevel, nSpell, nIndex, nClass, nMetaMagic, nDomain, nSubSpell, nFeat, nSAIndex, nUses;
|
||||
string sSpellIcon, sMetaMagicText, sSubSpell, sClass, sIndex;
|
||||
while(nIndex < 10)
|
||||
{
|
||||
@@ -2533,9 +2563,10 @@ void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int
|
||||
if(nUses)
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE));
|
||||
if(nUses == 999) sText = "Unlimited";
|
||||
if(nUses == 999) sText = "";
|
||||
else sText = IntToString(nUses);
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sBaseName + " / " + sText + ")"));
|
||||
NuiSetBind(oPC, nToken, "uses_" + sIndex + "_text", JsonString(sText));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sBaseName + ")"));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
}
|
||||
@@ -2558,8 +2589,10 @@ void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int
|
||||
}
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon));
|
||||
if(GetHasFeat(nFeat, oAssociate))
|
||||
nUses = GetHasFeat(nFeat, oAssociate);
|
||||
if(nUses > 0)
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "uses_" + sIndex + "_text", JsonString(IntToString(nUses)));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
@@ -2577,18 +2610,27 @@ void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int
|
||||
sMetaMagicText = ai_GetSpellIconAttributes(oAssociate, nMetaMagic, nDomain);
|
||||
NuiSetBind(oPC, nToken, "metamagic_" + sIndex + "_text", JsonString(sMetaMagicText));
|
||||
nSAIndex = JsonGetInt(JsonArrayGet(jSpell, 6));
|
||||
if(nClass == 255 && GetSpellAbilityReady(oAssociate, nSAIndex))
|
||||
if(nClass == 255)
|
||||
{
|
||||
sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (Special Ability / " + IntToString(nLevel) + ")"));
|
||||
if(GetSpellAbilityReady(oAssociate, nSAIndex))
|
||||
{
|
||||
sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (Special Ability / " + IntToString(nLevel) + ")"));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
}
|
||||
else if(GetSpellUsesLeft(oAssociate, nClass, nSpell, nMetaMagic, nDomain))
|
||||
else
|
||||
{
|
||||
sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass)));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")"));
|
||||
nUses = GetSpellUsesLeft(oAssociate, nClass, nSpell, nMetaMagic, nDomain);
|
||||
if(nUses > 0)
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "uses_" + sIndex + "_text", JsonString(IntToString(nUses)));
|
||||
sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass)));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")"));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2641,9 +2683,10 @@ void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int
|
||||
if(nUses)
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE));
|
||||
if(nUses == 999) sText = "Unlimited";
|
||||
if(nUses == 999) sText = "";
|
||||
else sText = IntToString(nUses);
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sBaseName + " / " + sText + ")"));
|
||||
NuiSetBind(oPC, nToken, "uses_" + sIndex + "_text", JsonString(sText));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sBaseName + ")"));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
}
|
||||
@@ -2665,8 +2708,10 @@ void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int
|
||||
}
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_image", JsonString(sSpellIcon));
|
||||
if(GetHasFeat(nFeat, oAssociate))
|
||||
nUses = GetHasFeat(nFeat, oAssociate);
|
||||
if(nUses > 0)
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "uses_" + sIndex + "_text", JsonString(IntToString(nUses)));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
@@ -2695,14 +2740,20 @@ void ai_SetWidgetBinds(object oPC, object oAssociate, string sAssociateType, int
|
||||
sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (Special Ability / " + IntToString(nLevel) + ")"));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
}
|
||||
else if(GetSpellUsesLeft(oAssociate, nClass, nSpell, nMetaMagic, nDomain))
|
||||
else
|
||||
{
|
||||
sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass)));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")"));
|
||||
nUses = GetSpellUsesLeft(oAssociate, nClass, nSpell, nMetaMagic, nDomain);
|
||||
if(nUses > 0)
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "uses_" + sIndex + "_text", JsonString(IntToString(nUses)));
|
||||
sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass)));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")"));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
}
|
||||
else NuiSetBind(oPC, nToken, "btn_widget_" + sIndex + "_event", JsonBool(FALSE));
|
||||
}
|
||||
}
|
||||
else break;
|
||||
@@ -2729,7 +2780,19 @@ void ai_CreateWidgetNUI(object oPC, object oAssociate)
|
||||
jButton = NuiHeight(jButton, 35.0);
|
||||
jButton = NuiMargin(jButton, 0.0);
|
||||
jButton = NuiTooltip(jButton, NuiBind ("btn_open_main_tooltip"));
|
||||
jButton = NuiImageRegion(jButton, NuiRect(0.0, 0.0, 32.0, 35.0));
|
||||
string sPortrait = GetPortraitResRef(oAssociate);
|
||||
if(ResManGetAliasFor(sPortrait + "s", RESTYPE_TGA) != "")
|
||||
jButton = NuiImageRegion(jButton, NuiRect(0.0, 0.0, 32.0, 50.0));
|
||||
else if(ResManGetAliasFor(sPortrait + "m", RESTYPE_TGA) != "")
|
||||
jButton = NuiImageRegion(jButton, NuiRect(0.0, 0.0, 64.0, 100.0));
|
||||
else if(ResManGetAliasFor(sPortrait + "l", RESTYPE_TGA)!= "")
|
||||
jButton = NuiImageRegion(jButton, NuiRect(0.0, 0.0, 128.0, 200.0));
|
||||
else if(ResManGetAliasFor(sPortrait + "h", RESTYPE_TGA)!= "")
|
||||
jButton = NuiImageRegion(jButton, NuiRect(0.0, 0.0, 256.0, 400.0));
|
||||
else jButton = NuiImageRegion(jButton, NuiRect(0.0, 0.0, 64.0, 100.0));
|
||||
jButton = NuiAspect(jButton, 1.0);
|
||||
//jButton = NuiImageRegion(jButton, NuiRect(0.0, 0.0, 32.0, 35.0));
|
||||
//jButton = NuiImage(jButton, JsonInt(NUI_ASPECT_FIT100), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP));
|
||||
json jRow = JsonArrayInsert(JsonArray(), jButton);
|
||||
if(ai_GetWidgetButton(oPC, BTN_ASSOC_WIDGETS_OFF, oAssociate, sAssociateType))
|
||||
{
|
||||
@@ -3020,7 +3083,7 @@ void ai_CreateWidgetNUI(object oPC, object oAssociate)
|
||||
fQuickWidgetColumns += 1.0;
|
||||
int bAdd;
|
||||
float fSpellButtons;
|
||||
json jButton, jRectangle, jMetaMagic, jDrawList;
|
||||
json jButton, jRectangle, jMetaMagic, jDrawList, jUses;
|
||||
// Add row to the column.
|
||||
if(bVertical) jCol = JsonArrayInsert(jCol, NuiCol(jRow));
|
||||
else jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
@@ -3053,10 +3116,16 @@ void ai_CreateWidgetNUI(object oPC, object oAssociate)
|
||||
jButton = NuiWidth(NuiHeight(jButton, 35.0), 35.0);
|
||||
jButton = NuiMargin(jButton, 0.0);
|
||||
jButton = NuiTooltip(jButton, NuiBind("btn_widget_" + sIndex + "_tooltip"));
|
||||
jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0);
|
||||
// Metamagic text.
|
||||
jRectangle = NuiRect(4.0, 24.0, 10.0, 31.0);
|
||||
jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_" + sIndex + "_text"));
|
||||
jDrawList = JsonArrayInsert(JsonArray(), jMetaMagic);
|
||||
jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList);
|
||||
// Spell uses text.
|
||||
jRectangle = NuiRect(24.0, 2.0, 31.0, 8.0);
|
||||
jUses = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 255), jRectangle, NuiBind("uses_" + sIndex + "_text"));
|
||||
jDrawList = JsonArrayInsert(JsonArray(), jUses);
|
||||
jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList);
|
||||
jRow = JsonArrayInsert(jRow, jButton);
|
||||
fSpellButtons += 1.0;
|
||||
}
|
||||
@@ -3099,10 +3168,16 @@ void ai_CreateWidgetNUI(object oPC, object oAssociate)
|
||||
jButton = NuiWidth(NuiHeight(jButton, 35.0), 35.0);
|
||||
jButton = NuiMargin(jButton, 0.0);
|
||||
jButton = NuiTooltip(jButton, NuiBind("btn_widget_" + sIndex + "_tooltip"));
|
||||
jRectangle = NuiRect(4.0, 4.0, 10.0, 10.0);
|
||||
// Metamagic text.
|
||||
jRectangle = NuiRect(4.0, 24.0, 10.0, 31.0);
|
||||
jMetaMagic = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 0), jRectangle, NuiBind("metamagic_" + sIndex + "_text"));
|
||||
jDrawList = JsonArrayInsert(JsonArray(), jMetaMagic);
|
||||
jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList);
|
||||
// Spell uses text.
|
||||
jRectangle = NuiRect(24.0, 2.0, 31.0, 8.0);
|
||||
jUses = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 255), jRectangle, NuiBind("uses_" + sIndex + "_text"));
|
||||
jDrawList = JsonArrayInsert(JsonArray(), jUses);
|
||||
jButton = NuiDrawList(jButton, JsonBool(TRUE), jDrawList);
|
||||
jRow = JsonArrayInsert(jRow, jButton);
|
||||
fSpellButtons += 1.0;
|
||||
}
|
||||
@@ -3713,7 +3788,7 @@ json ai_CheckItemAbilities(json jQuickListArray, object oCreature, object oItem,
|
||||
if(nCharges) nUses = nCharges;
|
||||
else nUses = nPerDay;
|
||||
}
|
||||
sSpellIcon = Get2DAString("spells", "iConResRef", nSpell);
|
||||
sSpellIcon = Get2DAString("spells", "IconResRef", nSpell);
|
||||
}
|
||||
jSpell_Icon = JsonArrayInsert(jSpell_Icon, JsonString(sSpellIcon));
|
||||
jSpell_Text = JsonArrayInsert(jSpell_Text, JsonString(sSpellName));
|
||||
|
||||
@@ -282,6 +282,8 @@ void ai_CreateDMOptionsNUI(object oPC)
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 3 ******************************************************************* 500 / 129
|
||||
jRow = CreateButton(JsonArray(), "Plugin Manager", "btn_plugin_manager", 160.0f, 20.0f, -1.0, "btn_plugin_manager_tooltip");
|
||||
//jRow = JsonArrayInsert(jRow, NuiSpacer());
|
||||
//jRow = CreateButtonSelect(jRow, "Effect Icons", "btn_effect_icon", 160.0f, 20.0f, "btn_effect_icon_tooltip");
|
||||
jRow = JsonArrayInsert(jRow, NuiSpacer());
|
||||
jRow = CreateButton(jRow, "Widget Manager", "btn_widget_manager", 160.0f, 20.0f, -1.0, "btn_widget_manager_tooltip");
|
||||
// Add row to the column.
|
||||
@@ -331,7 +333,8 @@ void ai_CreateDMOptionsNUI(object oPC)
|
||||
jGroupRow = CreateTextEditBox(JsonArray(), "sPlaceHolder", "txt_perception_distance", 2, FALSE, 35.0f, 20.0f, "txt_perception_distance_tooltip");
|
||||
jGroupRow = CreateLabel(jGroupRow, "meters is the distance a monster can respond to allies.", "lbl_perception_distance", 411.0f, 20.0f, NUI_HALIGN_LEFT, 0, 0.0, "txt_perception_distance_tooltip");
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
jGroupRow = CreateCheckBox(JsonArray(), " Monsters can prebuff before combat starts.", "chbx_buff_monsters", 450.0, 20.0);
|
||||
jGroupRow = CreateCheckBox(JsonArray(), " Monsters buff before combat starts.", "chbx_buff_monsters", 275.0, 20.0, "chbx_buff_monsters_tooltip");
|
||||
jGroupRow = CreateCheckBox(jGroupRow, " Use all buff spells instead!", "chbx_full_buff", 210.0, 20.0, "chbx_full_buff_tooltip");
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
jGroupRow = CreateCheckBox(JsonArray(), " Monsters can use summons before combat starts.", "chbx_buff_summons", 450.0, 20.0);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
@@ -423,6 +426,10 @@ void ai_CreateDMOptionsNUI(object oPC)
|
||||
// Row 3
|
||||
NuiSetBind(oPC, nToken, "btn_plugin_manager_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_plugin_manager_tooltip", JsonString(" Manages external executable scripts."));
|
||||
int bEffectIcon = ai_GetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT);
|
||||
//NuiSetBind(oPC, nToken, "btn_effect_icon", JsonBool (bEffectIcon));
|
||||
//NuiSetBind(oPC, nToken, "btn_effect_icon_event", JsonBool(TRUE));
|
||||
//NuiSetBind(oPC, nToken, "btn_effect_icon_tooltip", JsonString(" When on sends effect icon reports to the chat screen."));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_manager_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_widget_manager_tooltip", JsonString(" Manages widgets the players have access to."));
|
||||
// Row 3 Label for AI RULES
|
||||
@@ -448,9 +455,15 @@ void ai_CreateDMOptionsNUI(object oPC)
|
||||
NuiSetBind(oPC, nToken, "txt_ai_difficulty_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_ai_difficulty", JsonString(IntToString(GetLocalInt(oModule, AI_RULE_AI_DIFFICULTY))));
|
||||
NuiSetBindWatch(oPC, nToken, "txt_ai_difficulty", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_monsters_check", JsonBool(GetLocalInt(oModule, AI_RULE_BUFF_MONSTERS)));
|
||||
int bMonsterBuff = GetLocalInt(oModule, AI_RULE_BUFF_MONSTERS);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_monsters_check", JsonBool(bMonsterBuff));
|
||||
NuiSetBindWatch(oPC, nToken, "chbx_buff_monsters_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_monsters_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_monsters_tooltip", JsonString(" Monsters will cast all longer duration buff spells just before combat starts."));
|
||||
NuiSetBind(oPC, nToken, "chbx_full_buff_check", JsonBool(GetLocalInt(oModule, AI_RULE_FULL_BUFF_MONSTERS)));
|
||||
NuiSetBindWatch(oPC, nToken, "chbx_full_buff_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_full_buff_event", JsonBool(bMonsterBuff));
|
||||
NuiSetBind(oPC, nToken, "chbx_full_buff_tooltip", JsonString(" Monsters will cast all buff spells just before combat starts! VERY DIFFICULTY!"));
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_summons_check", JsonBool(GetLocalInt(oModule, AI_RULE_PRESUMMON)));
|
||||
NuiSetBindWatch(oPC, nToken, "chbx_buff_summons_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_buff_summons_event", JsonBool(TRUE));
|
||||
|
||||
@@ -207,6 +207,7 @@ void ai_CreateMonster(json jCreature, location lLocation, object oModule)
|
||||
{
|
||||
//WriteTimestampedLogEntry("0i_module, 181, " + JsonDump(jCreature, 1));
|
||||
object oCreature = JsonToObject(jCreature, lLocation, OBJECT_INVALID, TRUE);
|
||||
if(AI_DEBUG) ai_Debug("0i_module", "210", "Creating: " + GetName(oCreature));
|
||||
// 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))
|
||||
@@ -295,6 +296,7 @@ int ai_ChangeMonster(object oCreature, object oModule)
|
||||
{
|
||||
SetIsDestroyable(TRUE, FALSE, FALSE, oCreature);
|
||||
location lLocation = GetLocation(oCreature);
|
||||
if(AI_DEBUG) ai_Debug("0i_module", "299", "Destroying: " + GetName(oCreature));
|
||||
DestroyObject(oCreature);
|
||||
AssignCommand(oModule, DelayCommand(1.0, ai_CreateMonster(jCreature, lLocation, oModule)));
|
||||
DeleteLocalInt(oModule, AI_MONSTER_CHANGED);
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
void ai_SetupPlayerTarget();
|
||||
// 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.
|
||||
@@ -30,6 +28,13 @@ 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_EnterAssociateTargetMode(object oPC, object oAssociate)
|
||||
{
|
||||
SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate);
|
||||
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION");
|
||||
SetLocalInt(oPC, AI_TARGET_MODE_ON, TRUE);
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
|
||||
}
|
||||
void ai_SetupPlayerTarget()
|
||||
{
|
||||
object oModule = GetModule();
|
||||
@@ -40,129 +45,7 @@ void ai_SetupPlayerTarget()
|
||||
}
|
||||
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)
|
||||
void ai_ActionAssociate(object oPC, object oTarget, location lLocation, int bActionAll = FALSE)
|
||||
{
|
||||
object oAssociate = OBJECT_SELF;
|
||||
if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) &&
|
||||
@@ -233,7 +116,7 @@ void ai_ActionAssociate(object oPC, object oTarget, location lLocation)
|
||||
if(ai_ReactToTrap(oAssociate, oTarget, TRUE)) bStopAction = TRUE;
|
||||
if(bStopAction)
|
||||
{
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
|
||||
ai_EnterAssociateTargetMode(oPC, oAssociate);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -258,7 +141,7 @@ void ai_ActionAssociate(object oPC, object oTarget, location lLocation)
|
||||
{
|
||||
if(ai_ReactToTrap(oAssociate, oTarget, TRUE))
|
||||
{
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
|
||||
ai_EnterAssociateTargetMode(oPC, oAssociate);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -291,7 +174,7 @@ void ai_ActionAssociate(object oPC, object oTarget, location lLocation)
|
||||
if(GetTrapDetectedBy(oTarget, oAssociate)) ai_ReactToTrap(oAssociate, oTarget, TRUE);
|
||||
}
|
||||
}
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
|
||||
if(!bActionAll) ai_EnterAssociateTargetMode(oPC, oAssociate);
|
||||
}
|
||||
void ai_ActionAllAssociates(object oPC, object oTarget, location lLocation)
|
||||
{
|
||||
@@ -300,12 +183,12 @@ void ai_ActionAllAssociates(object oPC, object oTarget, location lLocation)
|
||||
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));
|
||||
if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation, TRUE));
|
||||
}
|
||||
for(nIndex = 2; nIndex < 6; nIndex++)
|
||||
{
|
||||
oAssociate = GetAssociate(nIndex, oPC);
|
||||
if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation));
|
||||
if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation, TRUE));
|
||||
}
|
||||
}
|
||||
void ai_SelectFollowTarget(object oPC, object oAssociate, object oTarget)
|
||||
@@ -343,34 +226,6 @@ void ai_SelectFollowTarget(object oPC, object oAssociate, object oTarget)
|
||||
}
|
||||
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;
|
||||
@@ -642,17 +497,18 @@ void ai_SelectWidgetSpellTarget(object oPC, object oAssociate, string sElem)
|
||||
{
|
||||
object oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5)));
|
||||
int nBaseItemType = GetBaseItemType(oItem);
|
||||
int nIprpSubType = JsonGetInt(JsonArrayGet(jSpell, 4));
|
||||
itemproperty ipProperty = GetFirstItemProperty(oItem);
|
||||
while(GetIsItemPropertyValid(ipProperty))
|
||||
{
|
||||
if(nIprpSubType == GetItemPropertySubType(ipProperty)) break;
|
||||
ipProperty = GetNextItemProperty(oItem);
|
||||
}
|
||||
if(Get2DAString("spells", "Range", nSpell) == "P" || // Self
|
||||
nBaseItemType == BASE_ITEM_ENCHANTED_POTION ||
|
||||
nBaseItemType == BASE_ITEM_POTIONS)
|
||||
nBaseItemType == BASE_ITEM_POTIONS ||
|
||||
nIprpSubType == IP_CONST_CASTSPELL_UNIQUE_POWER_SELF_ONLY)
|
||||
{
|
||||
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));
|
||||
|
||||
@@ -149,12 +149,12 @@ void ai_SetupAllyHealingTargets(object oCaster, object oPC);
|
||||
// Clears the casters buff targets.
|
||||
void ai_ClearBuffTargets(object oCaster, string sVariable);
|
||||
// Cycles through a casters spells casting all buffs via actions.
|
||||
void ai_ActionCastMemorizedBuff(struct stSpell stSpell);
|
||||
void ai_ActionCastMemorizedBuff(struct stSpell stSpell, float fDelay, int bInstantSpell);
|
||||
// Cycles through a casters spells casting all buffs via actions.
|
||||
void ai_ActionCastKnownBuff(struct stSpell stSpell);
|
||||
void ai_ActionCastKnownBuff(struct stSpell stSpell, float fDelay, int bInstantSpell);
|
||||
// Checks oCaster for buffing spells and casts them based on nTarget;
|
||||
// These are cast as actions and will happen at the speed based on
|
||||
// AI_HENCHMAN_BUFF_DELAY, but are still actions.
|
||||
// These are cast as actions and will happen at the speed based on the delay set
|
||||
// by the player. 6.0 seconds to 0.1 second. Default 0.1 second.
|
||||
// nTarget is 0-9 where 0 is all targets, 1 is oPC, 2 is the caster
|
||||
// 3 Familiar, 4 is Animal Companion, 5 is Summons, 6 is Dominated, and 7+ is henchman.
|
||||
// Targets must be defined in variable AI_ALLY_TARGET_* where * is 1 to #.
|
||||
@@ -1314,7 +1314,7 @@ int ai_CheckAndCastSpell(object oCaster, int nSpell, int nSpellGroup, float fDel
|
||||
// Search all memorized spells for the spell.
|
||||
if(Get2DAString("classes", "MemorizesSpells", nClass) == "1")
|
||||
{
|
||||
// Check each level starting with the highest to lowest.
|
||||
// Check each level starting with the lowest to the highest.
|
||||
nSpellLevel = 0;
|
||||
while(nSpellLevel < 10)
|
||||
{
|
||||
@@ -1326,6 +1326,8 @@ int ai_CheckAndCastSpell(object oCaster, int nSpell, int nSpellGroup, float fDel
|
||||
if(GetMemorizedSpellReady(oCaster, nClass, nSpellLevel, nSpellSlot))
|
||||
{
|
||||
nMemorizedSpell = GetMemorizedSpellId(oCaster, nClass, nSpellLevel, nSpellSlot);
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "1326", "nMemorizedSpell: " + IntToString(nMemorizedSpell) +
|
||||
" nSpell: " + IntToString(nSpell));
|
||||
if(nMemorizedSpell == nSpell)
|
||||
{
|
||||
ai_CastMemorizedSpell(oCaster, nClass, nSpellLevel, nSpellSlot, oTarget, FALSE, oPC);
|
||||
@@ -1564,7 +1566,7 @@ void ai_CheckForPerDayItems(object oCreature, object oPC, int nBuffType)
|
||||
nCntr++;
|
||||
}
|
||||
}
|
||||
void ai_CheckForBuffSpells(struct stSpell stSpell)
|
||||
void ai_CheckForBuffSpells(struct stSpell stSpell, float fDelay, int bInstantSpell)
|
||||
{
|
||||
ai_SetupAllyTargets(stSpell.oCaster, stSpell.oPC);
|
||||
stSpell.nPosition = 1;
|
||||
@@ -1585,13 +1587,13 @@ void ai_CheckForBuffSpells(struct stSpell stSpell)
|
||||
if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1")
|
||||
{
|
||||
stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell));
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell, fDelay, bInstantSpell));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell));
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell, fDelay, bInstantSpell));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1599,7 +1601,7 @@ void ai_CheckForBuffSpells(struct stSpell stSpell)
|
||||
}
|
||||
ai_CheckForPerDayItems(stSpell.oCaster, stSpell.oPC, stSpell.nBuffType);
|
||||
}
|
||||
void ai_ActionCastMemorizedSummons(struct stSpell stSpell)
|
||||
void ai_ActionCastMemorizedSummons(struct stSpell stSpell, float fDelay, int bInstantSpell)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "1122", "Start of ActionCastMemorizedSummons!");
|
||||
int nSpell;
|
||||
@@ -1625,14 +1627,14 @@ void ai_ActionCastMemorizedSummons(struct stSpell stSpell)
|
||||
if(Get2DAString("ai_spells", "Category", nSpell) == "S")
|
||||
{
|
||||
SetLocalInt(stSpell.oCaster, "AI_USED_SPELL_GROUP_-2", TRUE);
|
||||
ai_CastMemorizedSpell(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot, stSpell.oCaster, TRUE, stSpell.oPC);
|
||||
ai_CastMemorizedSpell(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot, stSpell.oCaster, bInstantSpell, stSpell.oPC);
|
||||
stSpell.nPosition = 1;
|
||||
stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster);
|
||||
stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2;
|
||||
stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
stSpell.nSlot = 0;
|
||||
DelayCommand(2.0, ai_SetupAllyTargets(stSpell.oCaster, stSpell.oPC));
|
||||
DelayCommand(2.0 + 0.5, AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell)));
|
||||
DelayCommand(2.0 + 0.5, AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell, fDelay, bInstantSpell)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1662,14 +1664,14 @@ void ai_ActionCastMemorizedSummons(struct stSpell stSpell)
|
||||
else
|
||||
{
|
||||
stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell));
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell, fDelay, bInstantSpell));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ai_CheckForBuffSpells(stSpell);
|
||||
ai_CheckForBuffSpells(stSpell, fDelay, bInstantSpell);
|
||||
}
|
||||
void ai_ActionCastKnownSummons(struct stSpell stSpell)
|
||||
void ai_ActionCastKnownSummons(struct stSpell stSpell, float fDelay, int bInstantSpell)
|
||||
{
|
||||
//ai_Debug("0i_spells", "1184", "Start of ActionCastKnownSummons!");
|
||||
int nSpell;
|
||||
@@ -1697,14 +1699,14 @@ void ai_ActionCastKnownSummons(struct stSpell stSpell)
|
||||
{
|
||||
SetLocalInt(stSpell.oCaster, "AI_USED_SPELL_GROUP_S", TRUE);
|
||||
//ai_Debug("0i_spells", "1209", "nSpell: " + IntToString(nSpell));
|
||||
ai_CastKnownSpell(stSpell.oCaster, stSpell.nClass, nSpell, stSpell.oCaster, TRUE, stSpell.oPC);
|
||||
ai_CastKnownSpell(stSpell.oCaster, stSpell.nClass, nSpell, stSpell.oCaster, bInstantSpell, stSpell.oPC);
|
||||
stSpell.nPosition = 1;
|
||||
stSpell.nClass = GetClassByPosition(stSpell.nPosition, stSpell.oCaster);
|
||||
stSpell.nLevel = (GetLevelByPosition(stSpell.nPosition, stSpell.oCaster) + 1) / 2;
|
||||
stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
stSpell.nSlot = 0;
|
||||
ai_SetupAllyTargets(stSpell.oCaster, stSpell.oPC);
|
||||
DelayCommand(AI_HENCHMAN_BUFF_DELAY, AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell)));
|
||||
DelayCommand(fDelay, AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell, fDelay, bInstantSpell)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1731,15 +1733,15 @@ void ai_ActionCastKnownSummons(struct stSpell stSpell)
|
||||
if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1")
|
||||
{
|
||||
stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell));
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell, fDelay, bInstantSpell));
|
||||
return;
|
||||
}
|
||||
else stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
}
|
||||
}
|
||||
ai_CheckForBuffSpells(stSpell);
|
||||
ai_CheckForBuffSpells(stSpell, fDelay, bInstantSpell);
|
||||
}
|
||||
void ai_ActionCastMemorizedBuff(struct stSpell stSpell)
|
||||
void ai_ActionCastMemorizedBuff(struct stSpell stSpell, float fDelay, int bInstantSpell)
|
||||
{
|
||||
int nSpell;
|
||||
string sBuffGroup, sBuffTarget;
|
||||
@@ -1782,9 +1784,9 @@ void ai_ActionCastMemorizedBuff(struct stSpell stSpell)
|
||||
" oTarget: " + GetName(oTarget));
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
ai_CastMemorizedSpell(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot, oTarget, TRUE, stSpell.oPC);
|
||||
ai_CastMemorizedSpell(stSpell.oCaster, stSpell.nClass, stSpell.nLevel, stSpell.nSlot, oTarget, bInstantSpell, stSpell.oPC);
|
||||
stSpell.nSlot++;
|
||||
DelayCommand(AI_HENCHMAN_BUFF_DELAY, AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell)));
|
||||
DelayCommand(fDelay, AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell, fDelay, bInstantSpell)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1815,14 +1817,14 @@ void ai_ActionCastMemorizedBuff(struct stSpell stSpell)
|
||||
else
|
||||
{
|
||||
stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell));
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell, fDelay, bInstantSpell));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ai_CheckForPerDayItems(stSpell.oCaster, stSpell.oPC, stSpell.nBuffType);
|
||||
}
|
||||
void ai_ActionCastKnownBuff(struct stSpell stSpell)
|
||||
void ai_ActionCastKnownBuff(struct stSpell stSpell, float fDelay, int bInstantSpell)
|
||||
{
|
||||
int nSpell;
|
||||
string sBuffGroup, sBuffTarget;
|
||||
@@ -1867,9 +1869,9 @@ void ai_ActionCastKnownBuff(struct stSpell stSpell)
|
||||
// " oTarget: " + GetName(oTarget));
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
ai_CastKnownSpell(stSpell.oCaster, stSpell.nClass, nSpell, oTarget, TRUE, stSpell.oPC);
|
||||
ai_CastKnownSpell(stSpell.oCaster, stSpell.nClass, nSpell, oTarget, bInstantSpell, stSpell.oPC);
|
||||
stSpell.nSlot++;
|
||||
DelayCommand(AI_HENCHMAN_BUFF_DELAY, AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell)));
|
||||
DelayCommand(fDelay, AssignCommand(stSpell.oCaster, ai_ActionCastKnownBuff(stSpell, fDelay, bInstantSpell)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1897,7 +1899,7 @@ void ai_ActionCastKnownBuff(struct stSpell stSpell)
|
||||
if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1")
|
||||
{
|
||||
stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell));
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedBuff(stSpell, fDelay, bInstantSpell));
|
||||
return;
|
||||
}
|
||||
else stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
@@ -1919,8 +1921,12 @@ void ai_CastBuffs(object oCaster, int nBuffType, int nTarget, object oPC)
|
||||
stSpell.nBuffType = nBuffType;
|
||||
stSpell.nTarget = nTarget;
|
||||
stSpell.nPosition = 1;
|
||||
float fDelay = GetLocalFloat(stSpell.oCaster, AI_DELAY_BUFF_CASTING);
|
||||
int bInstantSpell;
|
||||
if(fDelay < 4.9) bInstantSpell = TRUE;
|
||||
else fDelay = 6.0;
|
||||
// Look for summons spells on All, Long durations and the whole party.
|
||||
if((nBuffType == 1 || nBuffType == 3) && nTarget == 0)
|
||||
if((nBuffType == 1 || nBuffType == 3) && nTarget == 0 && GetAssociate(ASSOCIATE_TYPE_SUMMONED, oCaster) == OBJECT_INVALID)
|
||||
{
|
||||
while(stSpell.nPosition <= AI_MAX_CLASSES_PER_CHARACTER)
|
||||
{
|
||||
@@ -1935,13 +1941,13 @@ void ai_CastBuffs(object oCaster, int nBuffType, int nTarget, object oPC)
|
||||
if(Get2DAString("classes", "MemorizesSpells", stSpell.nClass) == "1")
|
||||
{
|
||||
stSpell.nMaxSlots = GetMemorizedSpellCountByLevel(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedSummons(stSpell));
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastMemorizedSummons(stSpell, fDelay, bInstantSpell));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
stSpell.nMaxSlots = GetKnownSpellCount(stSpell.oCaster, stSpell.nClass, stSpell.nLevel);
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastKnownSummons(stSpell));
|
||||
AssignCommand(stSpell.oCaster, ai_ActionCastKnownSummons(stSpell, fDelay, bInstantSpell));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1950,7 +1956,7 @@ void ai_CastBuffs(object oCaster, int nBuffType, int nTarget, object oPC)
|
||||
// Exit here; if we summoned a monster then it linked off of that spell
|
||||
// cast to continue the action queue for all buff spell cast actions.
|
||||
}
|
||||
ai_CheckForBuffSpells(stSpell);
|
||||
ai_CheckForBuffSpells(stSpell, fDelay, bInstantSpell);
|
||||
}
|
||||
int ai_CastSpontaneousCure(object oCreature, object oTarget, object oPC)
|
||||
{
|
||||
@@ -2349,7 +2355,7 @@ void ai_CastWidgetSpell(object oPC, object oAssociate, object oTarget, location
|
||||
// " oTarget: " + GetName(oTarget) +
|
||||
// " nMetaMagic: " + IntToString(nMetaMagic) +
|
||||
// " nDomain: " + IntToString(nDomain));
|
||||
if(GetCurrentAction(oAssociate) != ACTION_CASTSPELL) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE));
|
||||
if(GetCurrentAction(oAssociate) != ACTION_CASTSPELL) AssignCommand(oAssociate, ai_ClearCreatureActions(FALSE));
|
||||
if(!GetIsObjectValid(oTarget))
|
||||
{
|
||||
AssignCommand(oAssociate, ActionCastSpellAtLocation(nSpell, lLocation, nMetaMagic, FALSE, 0, FALSE, -1, FALSE, nDomain));
|
||||
@@ -2371,7 +2377,7 @@ void ai_UseWidgetFeat(object oPC, object oAssociate, object oTarget, location lL
|
||||
// We use nLevel at -1 to denote this is a feat with a subradial spell.
|
||||
int nSubSpell;
|
||||
if(nLevel == -1) nSubSpell = JsonGetInt(JsonArrayGet(jFeat, 0));
|
||||
if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE));
|
||||
if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(FALSE));
|
||||
//SendMessageToPC(oPC, "0i_spells, 2104, nFeat: " + IntToString(nFeat) + " oTarget: " + GetName(oTarget));
|
||||
if(!GetIsObjectValid(oTarget))
|
||||
{
|
||||
@@ -2392,7 +2398,7 @@ void ai_UseWidgetItem(object oPC, object oAssociate, object oTarget, location lL
|
||||
int nIprpSubType = JsonGetInt(JsonArrayGet(jItem, 4));
|
||||
object oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jItem, 5)));
|
||||
itemproperty ipProperty;
|
||||
if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE));
|
||||
if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(FALSE));
|
||||
if(nSpell == SPELL_HEALINGKIT)
|
||||
{
|
||||
ipProperty = GetFirstItemProperty(oItem);
|
||||
@@ -2409,9 +2415,9 @@ void ai_UseWidgetItem(object oPC, object oAssociate, object oTarget, location lL
|
||||
if(nIprpSubType == GetItemPropertySubType(ipProperty)) break;
|
||||
ipProperty = GetNextItemProperty(oItem);
|
||||
}
|
||||
if(!GetIsObjectValid(oTarget))
|
||||
if(GetIsObjectValid(oTarget))
|
||||
{
|
||||
AssignCommand(oAssociate, ActionUseItemAtLocation(oItem, ipProperty, lLocation));
|
||||
AssignCommand(oAssociate, ActionUseItemOnObject(oItem, ipProperty, oTarget));
|
||||
}
|
||||
else AssignCommand(oAssociate, ActionUseItemOnObject(oItem, ipProperty, oTarget));
|
||||
else AssignCommand(oAssociate, ActionUseItemAtLocation(oItem, ipProperty, lLocation));
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ void ai_ClearCreatureActions(int bClearCombatState = FALSE)
|
||||
void ai_SetLastAction(object oCreature, int nAction = AI_LAST_ACTION_NONE)
|
||||
{
|
||||
SetLocalInt(oCreature, sLastActionVarname, nAction);
|
||||
SetLocalInt(oCreature, sLastActionTimeVarname, ai_GetCurrentTimeStamp());
|
||||
}
|
||||
int ai_CompareLastAction(object oCreature, int nAction)
|
||||
{
|
||||
|
||||
@@ -219,13 +219,13 @@ int ai_GetHasTalent(object oCreature, int nTalent);
|
||||
// Type 4)item 0-type, 1-spell, 2-item object, 3-level, 4-slot.
|
||||
// jJsonLevel is the level to place the talent in the json array
|
||||
// maybe different then the talents actual level which is passed in nLevel.
|
||||
void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bBuff, int bDisablePreBuffs, object oItem = OBJECT_INVALID);
|
||||
void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bBuff, int bPreBuff, int bFullBuff, object oItem = OBJECT_INVALID);
|
||||
// Removes a talent nSlotIndex from jLevel in jCategory.
|
||||
void ai_RemoveTalent(object oCreature, json jCategory, json jLevel, string sCategory, int nLevel, int nSlotIndex);
|
||||
// Saves a creatures talents to variables upon them for combat use.
|
||||
// bMonster will check to see if they should be buffed when we set the talents.
|
||||
// bDisablePrebuffs - Tells the talent system
|
||||
void ai_SetCreatureTalents(object oCreature, int bMonster, int bDisablePreBuffs = FALSE);
|
||||
// bForceTalentSetup - Tells the talent system to force a talent setup but no Buffing.
|
||||
void ai_SetCreatureTalents(object oCreature, int bMonster, int bForceTalentSetup = FALSE);
|
||||
// Return TRUE if oCreature spontaneously casts a cure spell from a talent in sCategory.
|
||||
int ai_UseSpontaneousCureTalentFromCategory(object oCreature, string sCategory, int nInMelee, int nDamage, object oTarget = OBJECT_INVALID);
|
||||
// Returns TRUE if oCreature uses jTalent on oTarget.
|
||||
@@ -488,12 +488,13 @@ int ai_CheckTalentsVsConditions(object oCreature, int nConditions, int nInMelee,
|
||||
{
|
||||
nTalentUsed = ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, AI_TALENT_CURE, nInMelee, oTarget);
|
||||
// -1 means it was a memorized spell and we need to remove it.
|
||||
if(nTalentUsed == -1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, AI_TALENT_CURE, nLevel, nSlotIndex);
|
||||
return TRUE;
|
||||
}
|
||||
else if(nTalentUsed) return TRUE;
|
||||
//if(nTalentUsed == -1)
|
||||
//{
|
||||
// ai_RemoveTalent(oCreature, jCategory, jLevel, AI_TALENT_CURE, nLevel, nSlotIndex);
|
||||
// return TRUE;
|
||||
//}
|
||||
//else
|
||||
if(nTalentUsed) return TRUE;
|
||||
}
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
@@ -2044,10 +2045,8 @@ int ai_GetHasTalent(object oCreature, int nTalent)
|
||||
object ai_CheckTalentForBuffing(object oCreature, string sCategory, int nSpell)
|
||||
{
|
||||
// Should we buff this monster caster? Added legacy code just in case.
|
||||
if((sCategory == "P" || sCategory == "E" ||
|
||||
(sCategory == "S" && GetLocalInt(GetModule(), AI_RULE_PRESUMMON))) &&
|
||||
(GetLocalInt(GetModule(), AI_RULE_BUFF_MONSTERS) ||
|
||||
GetLocalInt(oCreature, "NW_GENERIC_MASTER") & 0x04000000)) return ai_GetBuffTarget(oCreature, nSpell);
|
||||
if(sCategory == "P" || sCategory == "E" ||
|
||||
(sCategory == "S" && GetLocalInt(GetModule(), AI_RULE_PRESUMMON))) return ai_GetBuffTarget(oCreature, nSpell);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
int ai_UseBuffTalent(object oCreature, int nClass, int nLevel, int nSlot, int nSpell, int nType, object oTarget, object oItem)
|
||||
@@ -2127,7 +2126,7 @@ int ai_SpellRestricted(int nSpell)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bMonster, int bDisablePreBuffs, object oItem = OBJECT_INVALID)
|
||||
void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bMonster, int bPreBuff, int bFullBuff, object oItem = OBJECT_INVALID)
|
||||
{
|
||||
// Players/Admins can restrict some spells.
|
||||
if(ai_SpellRestricted(nSpell)) return;
|
||||
@@ -2136,10 +2135,10 @@ void ai_SaveTalent(object oCreature, int nClass, int nJsonLevel, int nLevel, int
|
||||
// If it is a blank talent or it is an Area of Effect talent we skip.
|
||||
if(sCategory == "" || sCategory == "A") return;
|
||||
// Check to see if we should be prebuffing.
|
||||
if(bMonster && !bDisablePreBuffs)
|
||||
if(bMonster && bPreBuff)
|
||||
{
|
||||
int nSpellBuffDuration = StringToInt(Get2DAString("ai_spells", "Buff_Duration", nSpell));
|
||||
if(nSpellBuffDuration == 3)
|
||||
if(nSpellBuffDuration == 3 || (nSpellBuffDuration == 2 && bFullBuff))
|
||||
{
|
||||
object oTarget = ai_CheckTalentForBuffing(oCreature, sCategory, nSpell);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
@@ -2213,7 +2212,81 @@ void ai_RemoveTalentLevel(object oCreature, json jCategory, json jLevel, string
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1861", "jCategory: " + JsonDump(jCategory, 2));
|
||||
SetLocalJson(oCreature, sCategory, jCategory);
|
||||
}
|
||||
void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bDisablePreBuffs)
|
||||
/*******************************************************************************
|
||||
New Set Talents by Level then category.
|
||||
*******************************************************************************/
|
||||
/*void ai_SaveTalentByLevel(object oCreature, int nClass, int nJsonLevel, int nLevel, int nSlot, int nSpell, int nType, int bMonster, int bPreBuff, int bFullBuff, object oItem = OBJECT_INVALID)
|
||||
{
|
||||
// Players/Admins can restrict some spells.
|
||||
if(ai_SpellRestricted(nSpell)) return;
|
||||
// Get the talent category, we organize all talents by categories.
|
||||
string sCategory = Get2DAString("ai_spells", "Category", nSpell);
|
||||
// If it is a blank talent or it is an Area of Effect talent we skip.
|
||||
if(sCategory == "" || sCategory == "A") return;
|
||||
// Check to see if we should be prebuffing.
|
||||
if(bMonster && bPreBuff)
|
||||
{
|
||||
int nSpellBuffDuration = StringToInt(Get2DAString("ai_spells", "Buff_Duration", nSpell));
|
||||
if(nSpellBuffDuration == 3 || (nSpellBuffDuration == 2 && bFullBuff))
|
||||
{
|
||||
object oTarget = ai_CheckTalentForBuffing(oCreature, sCategory, nSpell);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1794", GetName(oCreature) + " is prebuffing with spell " + IntToString(nSpell));
|
||||
if(ai_UseBuffTalent(oCreature, nClass, nLevel, nSlot, nSpell, nType, oTarget, oItem)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
string sLevel = IntToString(nLevel);
|
||||
// Get the Level saved to Json.
|
||||
json jLevel = GetLocalJson(oCreature, "SPELL_LEVEL_" + sLevel);
|
||||
// If jLevel is not created we set it up.
|
||||
if(JsonGetType(jLevel) == JSON_TYPE_NULL) jLevel = JsonArray();
|
||||
json jTalent = JsonArray();
|
||||
if(nType == AI_TALENT_TYPE_SPELL || nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
{
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nType), 0);
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nSpell));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nClass));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nLevel));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nSlot));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonString(sCategory));
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_ITEM)
|
||||
{
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nType), 0);
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nSpell));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonString(ObjectToString(oItem)));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nLevel));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonInt(nSlot));
|
||||
jTalent = JsonArrayInsert(jTalent, JsonString(sCategory));
|
||||
}
|
||||
jLevel = JsonArrayInsert(jLevel, jTalent);
|
||||
SetLocalJson(oCreature, "SPELL_LEVEL_" + sLevel, jLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2265", sLevel + ": " + JsonDump(jLevel, 1));
|
||||
// Set AI_MAX_TALENT if this talent is higher than the maximum.
|
||||
if(nJsonLevel > GetLocalInt(oCreature, AI_MAX_LEVEL + sLevel))
|
||||
{
|
||||
SetLocalInt(oCreature, AI_MAX_LEVEL + sLevel, nJsonLevel);
|
||||
}
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2271", "AI_MAX_LEVEL: " +
|
||||
IntToString(GetLocalInt(oCreature, AI_MAX_LEVEL + sLevel)) +
|
||||
" nJsonLevel: " + IntToString(nJsonLevel));
|
||||
}
|
||||
// For removing used up spell slots.
|
||||
void ai_RemoveTalentByLevel(object oCreature, json jLevel, int nLevel, int nSlotIndex)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2278", "removing Talent from slot: " + IntToString(nSlotIndex));
|
||||
jLevel = JsonArrayDel(jLevel, nSlotIndex);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2280", "jLevel: " + JsonDump(jLevel, 2));
|
||||
SetLocalJson(oCreature, "SPELL_LEVEL_" + IntToString(nLevel), jLevel);
|
||||
}
|
||||
// For removing Sorcerer/Bard spell levels once used up.
|
||||
void ai_RemoveTalentLevelByLevel(object oCreature, int nLevel)
|
||||
{
|
||||
DeleteLocalJson(oCreature, "SPELL_LEVEL_" + IntToString(nLevel));
|
||||
}
|
||||
void ai_SetCreatureSpellTalentsByLevel(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1417", GetName(oCreature) + ": Setting Spell Talents for combat [Buff: " +
|
||||
IntToString(bMonster) + "].");
|
||||
@@ -2265,8 +2338,8 @@ void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bDisablePreB
|
||||
nAdjLevel = nLevel + nMetaMagic;
|
||||
if(nAdjLevel > 9) nAdjLevel = 9;
|
||||
}
|
||||
else nAdjLevel = nLevel; */
|
||||
ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bDisablePreBuffs);
|
||||
else nAdjLevel = nLevel;
|
||||
ai_SaveTalentByLevel(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
@@ -2295,7 +2368,7 @@ void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bDisablePreB
|
||||
IntToString(GetSpellUsesLeft(oCreature, nClass, nSpell)));
|
||||
if(GetSpellUsesLeft(oCreature, nClass, nSpell) > 0)
|
||||
{
|
||||
ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bDisablePreBuffs);
|
||||
ai_SaveTalentByLevel(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
@@ -2307,7 +2380,7 @@ void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bDisablePreB
|
||||
nClass = GetClassByPosition(nClassPosition, oCreature);
|
||||
}
|
||||
}
|
||||
void ai_SetCreatureSpecialAbilityTalents(object oCreature, int bMonster, int bDisablePreBuffs)
|
||||
void ai_SetCreatureSpecialAbilityTalentsByLevel(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1488", GetName(oCreature) + ": Setting Special Ability Talents for combat.");
|
||||
// Cycle through all the creatures special abilities.
|
||||
@@ -2322,13 +2395,13 @@ void ai_SetCreatureSpecialAbilityTalents(object oCreature, int bMonster, int bDi
|
||||
if(GetSpellAbilityReady(oCreature, nSpell))
|
||||
{
|
||||
nLevel = StringToInt(Get2DAString("spells", "Innate", nSpell));
|
||||
ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_SP_ABILITY, bMonster, bDisablePreBuffs);
|
||||
ai_SaveTalentByLevel(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_SP_ABILITY, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bDisablePreBuffs, int bEquiped = FALSE)
|
||||
void ai_CheckItemPropertiesByLevel(object oCreature, object oItem, int bMonster, int bPreBuff, int bFullBuff, int bEquiped = FALSE)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1509", "Checking Item properties on " + GetName(oItem));
|
||||
// We have established that we can use the item if it is equiped.
|
||||
@@ -2374,7 +2447,7 @@ void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bD
|
||||
nIprpSubType = GetItemPropertySubType(ipProp);
|
||||
nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType));
|
||||
nLevel = StringToInt(Get2DAString("iprp_spells", "InnateLvl", nIprpSubType));
|
||||
ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bDisablePreBuffs, oItem);
|
||||
ai_SaveTalentByLevel(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bPreBuff, bFullBuff, oItem);
|
||||
}
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_HEALERS_KIT)
|
||||
@@ -2385,7 +2458,7 @@ void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bD
|
||||
// Must also have ranks in healing kits.
|
||||
if(GetSkillRank(SKILL_HEAL, oCreature) > 0)
|
||||
{
|
||||
ai_SaveTalent(oCreature, 255, 7, 0, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bDisablePreBuffs, oItem);
|
||||
ai_SaveTalent(oCreature, 255, 7, 0, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bPreBuff, bFullBuff, oItem);
|
||||
}
|
||||
}
|
||||
if(bEquiped)
|
||||
@@ -2449,7 +2522,7 @@ void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bD
|
||||
// If any Immunity has been set then we need to save our Immunity json.
|
||||
if(bHasItemImmunity) SetLocalJson(oCreature, AI_TALENT_IMMUNITY, jImmunity);
|
||||
}
|
||||
void ai_SetCreatureItemTalents(object oCreature, int bMonster, int bDisablePreBuffs)
|
||||
void ai_SetCreatureItemTalentsByLevel(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1561", GetName(oCreature) + ": Setting Item Talents for combat.");
|
||||
int bEquiped;
|
||||
@@ -2465,7 +2538,7 @@ void ai_SetCreatureItemTalents(object oCreature, int bMonster, int bDisablePreBu
|
||||
// Does the item need to be equiped to use its powers?
|
||||
sSlots = Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1572", GetName(oItem) + " requires " + Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)) + " slots.");
|
||||
if(sSlots == "0x00000") ai_CheckItemProperties(oCreature, oItem, bMonster, bDisablePreBuffs);
|
||||
if(sSlots == "0x00000") ai_CheckItemPropertiesByLevel(oCreature, oItem, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
oItem = GetNextItemInInventory(oCreature);
|
||||
}
|
||||
@@ -2474,29 +2547,331 @@ void ai_SetCreatureItemTalents(object oCreature, int bMonster, int bDisablePreBu
|
||||
oItem = GetItemInSlot(nSlot, oCreature);
|
||||
while(nSlot < 11)
|
||||
{
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, TRUE);
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemPropertiesByLevel(oCreature, oItem, bMonster, bPreBuff, bFullBuff, TRUE);
|
||||
oItem = GetItemInSlot(++nSlot, oCreature);
|
||||
}
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oCreature);
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, TRUE);
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemPropertiesByLevel(oCreature, oItem, bMonster, bPreBuff, bFullBuff, TRUE);
|
||||
}
|
||||
void ai_SetCreatureTalents(object oCreature, int bMonster, int bDisablePreBuffs = FALSE)
|
||||
void ai_SetCreatureTalentsByLevel(object oCreature, int bMonster, int bForceTalentSetup = FALSE)
|
||||
{
|
||||
//json jCreature = ObjectToJson(oCreature);
|
||||
//if(AI_DEBUG) ai_Debug("0i_talents", "2072", GetName(oCreature) + " jCreature: " + JsonDump(jCreature, 4));
|
||||
if(GetLocalInt(oCreature, AI_TALENTS_SET) && !bDisablePreBuffs) return;
|
||||
if(GetLocalInt(oCreature, AI_TALENTS_SET) && !bForceTalentSetup) return;
|
||||
SetLocalInt(oCreature, AI_TALENTS_SET, TRUE);
|
||||
object oModule = GetModule();
|
||||
int bPreBuff = GetLocalInt(GetModule(), AI_RULE_BUFF_MONSTERS) || (GetLocalInt(oCreature, "NW_GENERIC_MASTER") & 0x04000000);
|
||||
int bFullBuff = GetLocalInt(GetModule(), AI_RULE_FULL_BUFF_MONSTERS);
|
||||
if(bForceTalentSetup) bPreBuff = FALSE;
|
||||
ai_Counter_Start();
|
||||
ai_SetCreatureSpellTalents(oCreature, bMonster, bDisablePreBuffs);
|
||||
ai_SetCreatureSpellTalentsByLevel(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Spell Talents");
|
||||
ai_SetCreatureSpecialAbilityTalents(oCreature, bMonster, bDisablePreBuffs);
|
||||
ai_SetCreatureSpecialAbilityTalentsByLevel(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Special Ability Talents");
|
||||
DeleteLocalJson(oCreature, AI_TALENT_IMMUNITY);
|
||||
ai_SetCreatureItemTalents(oCreature, bMonster, bDisablePreBuffs);
|
||||
ai_SetCreatureItemTalentsByLevel(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Item Talents");
|
||||
if(GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS) &&
|
||||
GetLocalInt(oModule, AI_RULE_PRESUMMON) && bMonster && !bDisablePreBuffs)
|
||||
GetLocalInt(oModule, AI_RULE_PRESUMMON) && bMonster && bPreBuff)
|
||||
{
|
||||
ai_TrySummonFamiliarTalent(oCreature);
|
||||
ai_TrySummonAnimalCompanionTalent(oCreature);
|
||||
}
|
||||
// AI_CAT_CURE is setup differently we save the level as the highest.
|
||||
//if(JsonGetType(GetLocalJson(oCreature, AI_TALENT_CURE)) != JSON_TYPE_NULL) SetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_CURE, 9);
|
||||
// With spontaneous cure spells we need to clear this as the number of spells don't count.
|
||||
//if(GetLevelByClass(CLASS_TYPE_CLERIC, oCreature)) SetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_HEALING, 0);
|
||||
} */
|
||||
/*******************************************************************************
|
||||
Old Set talents by category then level.
|
||||
*******************************************************************************/
|
||||
void ai_SetCreatureSpellTalents(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1417", GetName(oCreature) + ": Setting Spell Talents for combat [Buff: " +
|
||||
IntToString(bMonster) + "].");
|
||||
// Cycle through all classes and spells.
|
||||
int nClassPosition = 1, nMaxSlot, nLevel, nSlot, nSpell, nIndex, nMetaMagic;
|
||||
int nClass = GetClassByPosition(nClassPosition, oCreature);
|
||||
while(nClassPosition <= AI_MAX_CLASSES_PER_CHARACTER && nClass != CLASS_TYPE_INVALID)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1824", "nClass: " + IntToString(nClass) +
|
||||
" nClassPosition: " + IntToString(nClassPosition) +
|
||||
" SpellCaster: " + Get2DAString("classes", "SpellCaster", nClass) +
|
||||
" Memorized: " + Get2DAString("classes", "MemorizesSpells", nClass));
|
||||
if(Get2DAString("classes", "SpellCaster", nClass) == "1")
|
||||
{
|
||||
// Search all memorized spells for the spell.
|
||||
if(Get2DAString("classes", "MemorizesSpells", nClass) == "1")
|
||||
{
|
||||
// Check each level organizing from highest to lowest.
|
||||
nLevel = (GetLevelByPosition(nClassPosition, oCreature) + 1) / 2;
|
||||
if(nLevel > 9) nLevel = 9;
|
||||
while(nLevel > -1)
|
||||
{
|
||||
// Check each slot within each level.
|
||||
nMaxSlot = GetMemorizedSpellCountByLevel(oCreature, nClass, nLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1434", "nClass: " + IntToString(nClass) +
|
||||
" nLevel: " + IntToString(nLevel) + " nMaxSlot: " +
|
||||
IntToString(nMaxSlot));
|
||||
nSlot = 0;
|
||||
while(nSlot < nMaxSlot)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1440", "nSlot: " + IntToString(nSlot) + " nSpell: " +
|
||||
IntToString(GetMemorizedSpellId(oCreature, nClass, nLevel, nSlot)) + " spell memorized: " +
|
||||
IntToString(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot)));
|
||||
if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot) == 1)
|
||||
{
|
||||
nSpell = GetMemorizedSpellId(oCreature, nClass, nLevel, nSlot);
|
||||
/* Spells are already at the higher level when saved as a talent.
|
||||
// Move a spell up to a different JsonLevel as higher Jsonlevel
|
||||
// spells usually get cast first.
|
||||
nMetaMagic = GetMemorizedSpellMetaMagic(oCreature, nClass, nLevel, nSlot);
|
||||
if(nMetaMagic > 0)
|
||||
{
|
||||
if(nMetaMagic == METAMAGIC_STILL) nMetaMagic = 1;
|
||||
else if(nMetaMagic == METAMAGIC_EXTEND) nMetaMagic = 1;
|
||||
else if(nMetaMagic == METAMAGIC_SILENT) nMetaMagic = 1;
|
||||
else if(nMetaMagic == METAMAGIC_EMPOWER) nMetaMagic = 2;
|
||||
else if(nMetaMagic == METAMAGIC_MAXIMIZE) nMetaMagic = 3;
|
||||
else if(nMetaMagic == METAMAGIC_QUICKEN) nMetaMagic = 4;
|
||||
nAdjLevel = nLevel + nMetaMagic;
|
||||
if(nAdjLevel > 9) nAdjLevel = 9;
|
||||
}
|
||||
else nAdjLevel = nLevel; */
|
||||
ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
nLevel--;
|
||||
}
|
||||
}
|
||||
// Check non-memorized known lists for the spell.
|
||||
else
|
||||
{
|
||||
// Check each level starting with the highest to lowest.
|
||||
nLevel = (GetLevelByPosition(nClassPosition, oCreature) + 1) / 2;
|
||||
if(nLevel > 9) nLevel = 9;
|
||||
while(nLevel > -1)
|
||||
{
|
||||
// Check each slot within each level.
|
||||
nMaxSlot = GetKnownSpellCount(oCreature, nClass, nLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1462", "nClass: " + IntToString(nClass) +
|
||||
" nLevel: " + IntToString(nLevel) + " nMaxSlot: " +
|
||||
IntToString(nMaxSlot));
|
||||
nSlot = 0;
|
||||
while(nSlot < nMaxSlot)
|
||||
{
|
||||
nSpell = GetKnownSpellId(oCreature, nClass, nLevel, nSlot);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1469", "nSlot: " + IntToString(nSlot) +
|
||||
" nSpell: " + IntToString(nSpell) + " nUsesLeft: " +
|
||||
IntToString(GetSpellUsesLeft(oCreature, nClass, nSpell)));
|
||||
if(GetSpellUsesLeft(oCreature, nClass, nSpell) > 0)
|
||||
{
|
||||
ai_SaveTalent(oCreature, nClass, nLevel, nLevel, nSlot, nSpell, AI_TALENT_TYPE_SPELL, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
nLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
nClassPosition++;
|
||||
nClass = GetClassByPosition(nClassPosition, oCreature);
|
||||
}
|
||||
}
|
||||
void ai_SetCreatureSpecialAbilityTalents(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1488", GetName(oCreature) + ": Setting Special Ability Talents for combat.");
|
||||
// Cycle through all the creatures special abilities.
|
||||
int nMaxSpecialAbilities = GetSpellAbilityCount(oCreature);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1491", IntToString(nMaxSpecialAbilities) + " Spell abilities.");
|
||||
if(nMaxSpecialAbilities)
|
||||
{
|
||||
int nIndex, nSpell, nLevel;
|
||||
while(nIndex < nMaxSpecialAbilities)
|
||||
{
|
||||
nSpell = GetSpellAbilitySpell(oCreature, nIndex);
|
||||
if(GetSpellAbilityReady(oCreature, nSpell))
|
||||
{
|
||||
nLevel = StringToInt(Get2DAString("spells", "Innate", nSpell));
|
||||
ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_SP_ABILITY, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
void ai_CheckItemProperties(object oCreature, object oItem, int bMonster, int bPreBuff, int bFullBuff, int bEquiped = FALSE)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1509", "Checking Item properties on " + GetName(oItem));
|
||||
// We have established that we can use the item if it is equiped.
|
||||
if(!bEquiped && !ai_CheckIfCanUseItem(oCreature, oItem)) return;
|
||||
// Get or create an Immunity in json so we can check item immunities quickly.
|
||||
int nSpellImmunity, bHasItemImmunity, nPerDay, nCharges, nUses, bSaveTalent;
|
||||
json jImmunity = GetLocalJson(oCreature, AI_TALENT_IMMUNITY);
|
||||
if(JsonGetType(jImmunity) == JSON_TYPE_NULL) jImmunity = JsonArray();
|
||||
int nIprpSubType, nSpell, nLevel, nIPType, nIndex;
|
||||
itemproperty ipProp = GetFirstItemProperty(oItem);
|
||||
// Lets skip this if there are no properties.
|
||||
if(!GetIsItemPropertyValid(ipProp)) return;
|
||||
// Check for cast spell property and add them to the talent list.
|
||||
while(GetIsItemPropertyValid(ipProp))
|
||||
{
|
||||
nIPType = GetItemPropertyType(ipProp);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1895", "ItempropertyType(15/80/53): " + IntToString(nIPType));
|
||||
if(nIPType == ITEM_PROPERTY_CAST_SPELL)
|
||||
{
|
||||
bSaveTalent = TRUE;
|
||||
// Get how they use the item (charges or uses per day).
|
||||
nUses = GetItemPropertyCostTableValue(ipProp);
|
||||
if(nUses > 1 && nUses < 7)
|
||||
{
|
||||
nCharges = GetItemCharges(oItem);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1530", "Charges per use: " + IntToString(nUses) +
|
||||
" Item charges: " + IntToString(nCharges));
|
||||
if((nUses == IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE && nCharges < 1) ||
|
||||
(nUses == IP_CONST_CASTSPELL_NUMUSES_2_CHARGES_PER_USE && nCharges < 2) ||
|
||||
(nUses == IP_CONST_CASTSPELL_NUMUSES_3_CHARGES_PER_USE && nCharges < 3) ||
|
||||
(nUses == IP_CONST_CASTSPELL_NUMUSES_4_CHARGES_PER_USE && nCharges < 4) ||
|
||||
(nUses == IP_CONST_CASTSPELL_NUMUSES_5_CHARGES_PER_USE && nCharges < 5)) bSaveTalent = FALSE;
|
||||
}
|
||||
else if(nUses > 7 && nUses < 13)
|
||||
{
|
||||
nPerDay = GetItemPropertyUsesPerDayRemaining(oItem, ipProp);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1676", "Item uses: " + IntToString(nPerDay));
|
||||
if(nPerDay == 0) bSaveTalent = FALSE;
|
||||
}
|
||||
if(bSaveTalent)
|
||||
{
|
||||
// SubType is the ip spell index for iprp_spells.2da
|
||||
nIprpSubType = GetItemPropertySubType(ipProp);
|
||||
nSpell = StringToInt(Get2DAString("iprp_spells", "SpellIndex", nIprpSubType));
|
||||
nLevel = StringToInt(Get2DAString("iprp_spells", "InnateLvl", nIprpSubType));
|
||||
ai_SaveTalent(oCreature, 255, nLevel, nLevel, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bPreBuff, bFullBuff, oItem);
|
||||
}
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_HEALERS_KIT)
|
||||
{
|
||||
// Lets set Healing kits as Cure Light Wounds since they heal 1d20 in combat.
|
||||
nSpell = SPELL_CURE_MINOR_WOUNDS;
|
||||
// Save the healer kit as level 9 so we can use them first.
|
||||
// Must also have ranks in healing kits.
|
||||
if(GetSkillRank(SKILL_HEAL, oCreature) > 0)
|
||||
{
|
||||
ai_SaveTalent(oCreature, 255, 7, 0, nIndex, nSpell, AI_TALENT_TYPE_ITEM, bMonster, bPreBuff, bFullBuff, oItem);
|
||||
}
|
||||
}
|
||||
if(bEquiped)
|
||||
{
|
||||
if(nIPType == ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL)
|
||||
{
|
||||
bHasItemImmunity = TRUE;
|
||||
nSpellImmunity = GetItemPropertyCostTableValue(ipProp);
|
||||
nSpellImmunity = StringToInt(Get2DAString("iprp_spellcost", "SpellIndex", nSpellImmunity));
|
||||
//if(AI_DEBUG) ai_Debug("0i_talents", "1950", "SpellImmunity to " + Get2DAString("spells", "Label", nSpellImmunity));
|
||||
jImmunity = JsonArrayInsert(jImmunity, JsonInt(nSpellImmunity));
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_HASTE)
|
||||
{
|
||||
SetLocalInt(oCreature, sIPHasHasteVarname, TRUE);
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE)
|
||||
{
|
||||
int nBit, nIpSubType = GetItemPropertySubType(ipProp);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1957", "nIPSubType: " + IntToString(nIpSubType));
|
||||
if(nIpSubType == 0) nBit = DAMAGE_TYPE_BLUDGEONING;
|
||||
else if(nIpSubType == 1) nBit = DAMAGE_TYPE_PIERCING;
|
||||
else if(nIpSubType == 2) nBit = DAMAGE_TYPE_SLASHING;
|
||||
else if(nIpSubType == 5) nBit = DAMAGE_TYPE_MAGICAL;
|
||||
else if(nIpSubType == 6) nBit = DAMAGE_TYPE_ACID;
|
||||
else if(nIpSubType == 7) nBit = DAMAGE_TYPE_COLD;
|
||||
else if(nIpSubType == 8) nBit = DAMAGE_TYPE_DIVINE;
|
||||
else if(nIpSubType == 9) nBit = DAMAGE_TYPE_ELECTRICAL;
|
||||
else if(nIpSubType == 10) nBit = DAMAGE_TYPE_FIRE;
|
||||
else if(nIpSubType == 11) nBit = DAMAGE_TYPE_NEGATIVE;
|
||||
else if(nIpSubType == 12) nBit = DAMAGE_TYPE_POSITIVE;
|
||||
else if(nIpSubType == 13) nBit = DAMAGE_TYPE_SONIC;
|
||||
if(nBit > 0) ai_SetItemProperty(oCreature, sIPImmuneVarname, nBit, TRUE);
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_DAMAGE_RESISTANCE)
|
||||
{
|
||||
int nBit, nIpSubType = GetItemPropertySubType(ipProp);
|
||||
if(nIpSubType == 0) nBit = DAMAGE_TYPE_BLUDGEONING;
|
||||
else if(nIpSubType == 1) nBit = DAMAGE_TYPE_PIERCING;
|
||||
else if(nIpSubType == 2) nBit = DAMAGE_TYPE_SLASHING;
|
||||
else if(nIpSubType == 5) nBit = DAMAGE_TYPE_MAGICAL;
|
||||
else if(nIpSubType == 6) nBit = DAMAGE_TYPE_ACID;
|
||||
else if(nIpSubType == 7) nBit = DAMAGE_TYPE_COLD;
|
||||
else if(nIpSubType == 8) nBit = DAMAGE_TYPE_DIVINE;
|
||||
else if(nIpSubType == 9) nBit = DAMAGE_TYPE_ELECTRICAL;
|
||||
else if(nIpSubType == 10) nBit = DAMAGE_TYPE_FIRE;
|
||||
else if(nIpSubType == 11) nBit = DAMAGE_TYPE_NEGATIVE;
|
||||
else if(nIpSubType == 12) nBit = DAMAGE_TYPE_POSITIVE;
|
||||
else if(nIpSubType == 13) nBit = DAMAGE_TYPE_SONIC;
|
||||
if(nBit > 0) ai_SetItemProperty(oCreature, sIPResistVarname, nBit, TRUE);
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_DAMAGE_REDUCTION)
|
||||
{
|
||||
int nIpSubType = GetItemPropertySubType(ipProp);
|
||||
SetLocalInt(oCreature, sIPReducedVarname, nIpSubType);
|
||||
}
|
||||
}
|
||||
nIndex++;
|
||||
ipProp = GetNextItemProperty(oItem);
|
||||
}
|
||||
// If any Immunity has been set then we need to save our Immunity json.
|
||||
if(bHasItemImmunity) SetLocalJson(oCreature, AI_TALENT_IMMUNITY, jImmunity);
|
||||
}
|
||||
void ai_SetCreatureItemTalents(object oCreature, int bMonster, int bPreBuff, int bFullBuff)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1561", GetName(oCreature) + ": Setting Item Talents for combat.");
|
||||
int bEquiped;
|
||||
// Set the Immunities to -1 so we know they were set incase there are no immunities.
|
||||
SetLocalInt(oCreature, sIPReducedVarname, -1);
|
||||
string sSlots;
|
||||
// Cycle through all the creatures inventory items.
|
||||
object oItem = GetFirstItemInInventory(oCreature);
|
||||
while(oItem != OBJECT_INVALID)
|
||||
{
|
||||
if(GetIdentified(oItem))
|
||||
{
|
||||
// Does the item need to be equiped to use its powers?
|
||||
sSlots = Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1572", GetName(oItem) + " requires " + Get2DAString("baseitems", "EquipableSlots", GetBaseItemType(oItem)) + " slots.");
|
||||
if(sSlots == "0x00000") ai_CheckItemProperties(oCreature, oItem, bMonster, bPreBuff, bFullBuff);
|
||||
}
|
||||
oItem = GetNextItemInInventory(oCreature);
|
||||
}
|
||||
int nSlot;
|
||||
// Cycle through all the creatures equiped items.
|
||||
oItem = GetItemInSlot(nSlot, oCreature);
|
||||
while(nSlot < 11)
|
||||
{
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, bPreBuff, bFullBuff, TRUE);
|
||||
oItem = GetItemInSlot(++nSlot, oCreature);
|
||||
}
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oCreature);
|
||||
if(oItem != OBJECT_INVALID) ai_CheckItemProperties(oCreature, oItem, bMonster, bPreBuff, bFullBuff, TRUE);
|
||||
}
|
||||
void ai_SetCreatureTalents(object oCreature, int bMonster, int bForceTalentSetup = FALSE)
|
||||
{
|
||||
//json jCreature = ObjectToJson(oCreature);
|
||||
//if(AI_DEBUG) ai_Debug("0i_talents", "2072", GetName(oCreature) + " jCreature: " + JsonDump(jCreature, 4));
|
||||
if(GetLocalInt(oCreature, AI_TALENTS_SET) && !bForceTalentSetup) return;
|
||||
SetLocalInt(oCreature, AI_TALENTS_SET, TRUE);
|
||||
object oModule = GetModule();
|
||||
int bPreBuff = GetLocalInt(GetModule(), AI_RULE_BUFF_MONSTERS) || (GetLocalInt(oCreature, "NW_GENERIC_MASTER") & 0x04000000);
|
||||
int bFullBuff = GetLocalInt(GetModule(), AI_RULE_FULL_BUFF_MONSTERS);
|
||||
if(bForceTalentSetup) bPreBuff = FALSE;
|
||||
ai_Counter_Start();
|
||||
ai_SetCreatureSpellTalents(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Spell Talents");
|
||||
ai_SetCreatureSpecialAbilityTalents(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Special Ability Talents");
|
||||
DeleteLocalJson(oCreature, AI_TALENT_IMMUNITY);
|
||||
ai_SetCreatureItemTalents(oCreature, bMonster, bPreBuff, bFullBuff);
|
||||
ai_Counter_End(GetName(oCreature) + ": Item Talents");
|
||||
if(GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS) &&
|
||||
GetLocalInt(oModule, AI_RULE_PRESUMMON) && bMonster && bPreBuff)
|
||||
{
|
||||
ai_TrySummonFamiliarTalent(oCreature);
|
||||
ai_TrySummonAnimalCompanionTalent(oCreature);
|
||||
@@ -2622,20 +2997,6 @@ int ai_UseCreatureSpellTalent(object oCreature, json jLevel, json jTalent, strin
|
||||
}
|
||||
}
|
||||
if(ai_ArcaneSpellFailureTooHigh(oCreature, nClass, nLevel, nSlot)) return FALSE;
|
||||
if(Get2DAString("classes", "MemorizesSpells", nClass) == "1")
|
||||
{
|
||||
// Shouldn't need this anymore, we need to do a debug looking at this.
|
||||
if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot) < 1) return FALSE;
|
||||
if(ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget))
|
||||
{
|
||||
if(ai_CompareLastAction(oCreature, AI_LAST_ACTION_CAST_SPELL)) return -1;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1629", "Known caster Level: " + IntToString(nLevel) +
|
||||
" Uses : " + IntToString(GetSpellUsesLeft(oCreature, nClass, JsonGetInt(JsonArrayGet(jTalent, 1)))));
|
||||
if(!GetSpellUsesLeft(oCreature, nClass, JsonGetInt(JsonArrayGet(jTalent, 1)))) return -2;
|
||||
return ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget);
|
||||
}
|
||||
int ai_UseCreatureItemTalent(object oCreature, json jLevel, json jTalent, string sCategory, int nInMelee, object oTarget = OBJECT_INVALID)
|
||||
@@ -2691,6 +3052,178 @@ void ai_UpdateMaxTalentLevel(object oCreature, json jCategory, string sCategory,
|
||||
SetLocalInt(oCreature, AI_MAX_TALENT + sCategory, nLevel);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
New talent system that checks by level then category.
|
||||
*******************************************************************************/
|
||||
/*int ai_UseCreatureTalentByLevel(object oCreature, int nInMelee, int nLevel = 10, object oTarget = OBJECT_INVALID)
|
||||
{
|
||||
string sLevel = IntToString(nLevel);
|
||||
// Get the Max Talent Level to see if we even need to pull this talent.
|
||||
int nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_LEVEL + sLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2394", AI_MAX_LEVEL + sLevel + ": " +
|
||||
IntToString(nMaxTalentLevel) +
|
||||
" nLevel: " + IntToString(nLevel));
|
||||
if(nMaxTalentLevel == -1) return FALSE;
|
||||
// If there are no talents at higher levels then start at the lowest talent level.
|
||||
if(nMaxTalentLevel < nLevel) nLevel = nMaxTalentLevel;
|
||||
if(nLevel < 0 || nLevel > 10) nLevel = 9;
|
||||
json jTalent;
|
||||
int bHasTalent, nClass, nSlot, nType, nSlotIndex, nMaxSlotIndex, nTalentUsed, nSpell;
|
||||
int bUseMagic = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC);
|
||||
int bUseMagicItems = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC_ITEMS);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2413", "bUseMagic: " + IntToString(bUseMagic) +
|
||||
" bUseMagicItems: " + IntToString(bUseMagicItems));
|
||||
// Loop through nLevels starting at the highest then going to the lowest.
|
||||
// (i.e. the highest or best is our assumption).
|
||||
// Get the saved level from oCreature.
|
||||
json jLevel = GetLocalJson(oCreature, "SPELL_LEVEL_" + IntToString(nLevel));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "3091", "jLevel: " + IntToString(nLevel) + " " + JsonDump(jLevel, 2));
|
||||
if(JsonGetType(jCategory) == JSON_TYPE_NULL)
|
||||
{
|
||||
SetLocalInt(oCreature, AI_MAX_LEVEL + sCategory, -1);
|
||||
return FALSE;
|
||||
}
|
||||
while(nLevel > -1)
|
||||
{
|
||||
// Get the array of nLevel cycling down to 0.
|
||||
jLevel = JsonArrayGet(jCategory, nLevel);
|
||||
nMaxSlotIndex = JsonGetLength(jLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2422", "Level: " + IntToString(nLevel) +
|
||||
" nMaxSlotIndex: " + IntToString(nMaxSlotIndex));
|
||||
if(nMaxSlotIndex > 0)
|
||||
{
|
||||
bHasTalent = TRUE;
|
||||
// Get the talent within nLevel cycling from the first to the last.
|
||||
nSlotIndex = 0;
|
||||
while (nSlotIndex < nMaxSlotIndex)
|
||||
{
|
||||
jTalent= JsonArrayGet(jLevel, nSlotIndex);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2432", "nSlotIndex: " + IntToString(nSlotIndex) +
|
||||
" jTalent Type: " + IntToString(JsonGetInt(JsonArrayGet(jTalent, 0))));
|
||||
nType = JsonGetInt(JsonArrayGet(jTalent, 0));
|
||||
if(bUseMagic)
|
||||
{
|
||||
if(nType == AI_TALENT_TYPE_SPELL)
|
||||
{
|
||||
nTalentUsed = ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget);
|
||||
// -1 means it was a memorized spell and we need to remove it.
|
||||
if(nTalentUsed == -1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
return TRUE;
|
||||
}
|
||||
// There are no more spell slots left for non-memorizing caster so remove the level.
|
||||
else if(nTalentUsed == -2)
|
||||
{
|
||||
ai_RemoveTalentLevel(oCreature, jCategory, jLevel, sCategory, nLevel);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
}
|
||||
else if(nTalentUsed) return TRUE;
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
{
|
||||
// Special ability spells do not need to concentrate?!
|
||||
if(ai_CheckSpecialTalentsandUse(oCreature, jTalent, sCategory, nInMelee, oTarget))
|
||||
{
|
||||
// When the ability is used that slot is now not readied.
|
||||
// Multiple uses of the same spell are stored in different slots.
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bUseMagicItems && nType == AI_TALENT_TYPE_ITEM)
|
||||
{
|
||||
// Items do not need to concentrate.
|
||||
if(ai_UseCreatureItemTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "2473", "Checking if Item is used up: " +
|
||||
IntToString(JsonGetInt(JsonArrayGet(jTalent, 4))));
|
||||
if(JsonGetInt(JsonArrayGet(jTalent, 4)) == -1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
//else if(nType == AI_TALENT_TYPE_FEAT) {}
|
||||
nSlotIndex++;
|
||||
}
|
||||
}
|
||||
else if(!bHasTalent) SetLocalInt(oCreature, AI_MAX_LEVEL + sCategory, nLevel - 1);
|
||||
nLevel--;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
int ai_UseTalentByLevel(object oCreature, int nTalent, object oTarget)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1912", GetName(oCreature) + " is trying to use " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nTalent))) +
|
||||
" on " + GetName(oTarget));
|
||||
// Get the saved category from oCreature.
|
||||
string sCategory = Get2DAString("ai_spells", "Category", nTalent);
|
||||
json jCategory = GetLocalJson(oCreature, sCategory);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1917", "jCategory: " + sCategory + " " + JsonDump(jCategory, 2));
|
||||
if(JsonGetType(jCategory) == JSON_TYPE_NULL) return FALSE;
|
||||
json jLevel, jTalent;
|
||||
int nLevel, nClass, nSlot, nType, nSlotIndex, nMaxSlotIndex, nTalentUsed, nSpell;
|
||||
// Loop through nLevels down to nMinNoTalentLevel looking for the first talent
|
||||
// (i.e. the highest or best?).
|
||||
while(nLevel <= 9)
|
||||
{
|
||||
// Get the array of nLevel.
|
||||
jLevel = JsonArrayGet(jCategory, nLevel);
|
||||
nMaxSlotIndex = JsonGetLength(jLevel);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1925", "nLevel: " + IntToString(nLevel) +
|
||||
" nMaxSlotIndex: " + IntToString(nMaxSlotIndex));
|
||||
if(nMaxSlotIndex > 0)
|
||||
{
|
||||
// Get the talent within nLevel cycling from the first to the last.
|
||||
nSlotIndex = 0;
|
||||
while (nSlotIndex < nMaxSlotIndex)
|
||||
{
|
||||
jTalent= JsonArrayGet(jLevel, nSlotIndex);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1936", "nSlotIndex: " + IntToString(nSlotIndex) +
|
||||
" jTalent Type: " + IntToString(JsonGetInt(JsonArrayGet(jTalent, 0))));
|
||||
nSpell = JsonGetInt(JsonArrayGet(jTalent, 1));
|
||||
if(nSpell == nTalent)
|
||||
{
|
||||
nType = JsonGetInt(JsonArrayGet(jTalent, 0));
|
||||
if(nType == AI_TALENT_TYPE_SPELL || nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
{
|
||||
if(ai_UseTalentOnObject(oCreature, jTalent, oTarget, 0))
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_ITEM)
|
||||
{
|
||||
// Items do not need to concentrate.
|
||||
if(ai_UseCreatureItemTalent(oCreature, jLevel, jTalent, sCategory, 0, oTarget))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1955", "Checking if Item is used up: " +
|
||||
IntToString(JsonGetInt(JsonArrayGet(jTalent, 4))));
|
||||
if(JsonGetInt(JsonArrayGet(jTalent, 4)) == -1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
nSlotIndex++;
|
||||
}
|
||||
}
|
||||
nLevel++;
|
||||
}
|
||||
return FALSE;
|
||||
} */
|
||||
/*******************************************************************************
|
||||
Old talent system that checks by category then level.
|
||||
*******************************************************************************/
|
||||
int ai_UseCreatureTalent(object oCreature, string sCategory, int nInMelee, int nLevel = 10, object oTarget = OBJECT_INVALID)
|
||||
{
|
||||
// Get the Max Talent Level to see if we even need to pull this talent.
|
||||
@@ -2740,21 +3273,28 @@ int ai_UseCreatureTalent(object oCreature, string sCategory, int nInMelee, int n
|
||||
{
|
||||
if(nType == AI_TALENT_TYPE_SPELL)
|
||||
{
|
||||
nTalentUsed = ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget);
|
||||
// -1 means it was a memorized spell and we need to remove it.
|
||||
if(nTalentUsed == -1)
|
||||
// Check to make sure they still have this spell.
|
||||
nClass = JsonGetInt(JsonArrayGet(jTalent, 2));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "3290", GetName(oCreature) + " Memorizes Spells? " +
|
||||
Get2DAString("classes", "MemorizesSpells", nClass));
|
||||
if(Get2DAString("classes", "MemorizesSpells", nClass) == "1")
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
return TRUE;
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "3294", " Spell Memorized? " +
|
||||
IntToString(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlotIndex)));
|
||||
if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlotIndex) < 1)
|
||||
{
|
||||
ai_RemoveTalent(oCreature, jCategory, jLevel, sCategory, nLevel, nSlotIndex);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
}
|
||||
else if(ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget)) return TRUE;
|
||||
}
|
||||
// There are no more spell slots left for non-memorizing caster so remove the level.
|
||||
else if(nTalentUsed == -2)
|
||||
else if(!GetSpellUsesLeft(oCreature, nClass, JsonGetInt(JsonArrayGet(jTalent, 1))))
|
||||
{
|
||||
ai_RemoveTalentLevel(oCreature, jCategory, jLevel, sCategory, nLevel);
|
||||
if(nMaxSlotIndex == 1) ai_UpdateMaxTalentLevel(oCreature, jCategory, sCategory, nMaxTalentLevel, nLevel);
|
||||
nTalentUsed = FALSE;
|
||||
}
|
||||
else if(nTalentUsed) return TRUE;
|
||||
else if(ai_UseCreatureSpellTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget)) return TRUE;
|
||||
}
|
||||
else if(nType == AI_TALENT_TYPE_SP_ABILITY)
|
||||
{
|
||||
@@ -2769,7 +3309,7 @@ int ai_UseCreatureTalent(object oCreature, string sCategory, int nInMelee, int n
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bUseMagicItems && nType == AI_TALENT_TYPE_ITEM)
|
||||
else if(bUseMagicItems && nType == AI_TALENT_TYPE_ITEM)
|
||||
{
|
||||
// Items do not need to concentrate.
|
||||
if(ai_UseCreatureItemTalent(oCreature, jLevel, jTalent, sCategory, nInMelee, oTarget))
|
||||
@@ -2856,6 +3396,19 @@ int ai_UseTalent(object oCreature, int nTalent, object oTarget)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
// Lets do a check right before we cast the spell to see if the target is still good.
|
||||
void ai_CheckSpellTarget(object oCreature, object oTarget)
|
||||
{
|
||||
if(GetIsDead(oTarget))
|
||||
{
|
||||
//SendMessageToPC(GetFirstPC(), "0i_talents, 2864, " + GetName(oCreature) +
|
||||
//" is stopping our spell casting because " + GetName(oTarget) + " is dead!");
|
||||
//WriteTimestampedLogEntry("0i_talents, 2864, " + GetName(oCreature) +
|
||||
//" is stopping our spell casting because " + GetName(oTarget) + " is dead!");
|
||||
ai_ClearCreatureActions();
|
||||
ExecuteScript("0e_do_combat_rnd", oCreature);
|
||||
}
|
||||
}
|
||||
int ai_UseTalentOnObject(object oCreature, json jTalent, object oTarget, int nInMelee, int bCheckPosition = TRUE)
|
||||
{
|
||||
int nClass, nLevel, nSlot, nMetaMagic, nDomain;
|
||||
@@ -2955,7 +3508,14 @@ int ai_UseTalentOnObject(object oCreature, json jTalent, object oTarget, int nIn
|
||||
" nDomain: " + IntToString(nDomain) + " nClass: " + IntToString(nClass));
|
||||
ai_SetLastAction(oCreature, nSpell);
|
||||
ActionCastSpellAtObject(nSpell, oTarget, nMetaMagic, FALSE, nDomain, 0, FALSE, nClass, FALSE);
|
||||
// This was added to do a second check right before they cast to make sure
|
||||
// the target was not killed between us deciding to cast and then casting!
|
||||
DelayCommand(2.5, ai_CheckSpellTarget(oCreature, oTarget));
|
||||
ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature));
|
||||
// Temp Debug!!!!!
|
||||
//string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
//SendMessageToPC(GetFirstPC(), "0i_talents, 1859 " + GetName(oCreature) + " is casting " + sSpellName + " on " + GetName(oTarget));
|
||||
// Temp Debug!!!!!
|
||||
if(AI_DEBUG)
|
||||
{
|
||||
string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
@@ -3062,7 +3622,23 @@ int ai_UseTalentAtLocation(object oCreature, json jTalent, object oTarget, int n
|
||||
int ai_CheckSpecialTalentsandUse(object oCreature, json jTalent, string sCategory, int nInMelee, object oTarget)
|
||||
{
|
||||
int nSpell = JsonGetInt(JsonArrayGet(jTalent, 1));
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "1949", "nSpell: " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))) +
|
||||
// This checks to see if they tried to cast this spell last round and if we
|
||||
// are trying to cast it again before at least 3 seconds is up then the spell
|
||||
// is being canceled... remove this spell and look for another!
|
||||
if(ai_CompareLastAction(oCreature, nSpell) &&
|
||||
ai_GetCurrentTimeStamp() - GetLocalInt(oCreature, sLastActionTimeVarname) < 2)
|
||||
{
|
||||
if(AI_DEBUG)
|
||||
{
|
||||
int nLastTime = GetLocalInt(oCreature, sLastActionTimeVarname);
|
||||
int nCurrentTime = ai_GetCurrentTimeStamp();
|
||||
ai_Debug("0i_talents", "3634", "Same spell cast within less than 2 seconds!" +
|
||||
" nSpell: " + IntToString(nSpell) + " nLastActionTime: " + IntToString(nLastTime) +
|
||||
" nCurrentTime: " + IntToString(nCurrentTime) + " Difference: " + IntToString(nCurrentTime - nLastTime));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "3637", "nSpell: " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell))) +
|
||||
" sCategory: " + sCategory);
|
||||
if(sCategory == AI_TALENT_DISCRIMINANT_AOE)
|
||||
{
|
||||
|
||||
@@ -88,7 +88,30 @@ void main()
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
|
||||
else
|
||||
{
|
||||
if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
|
||||
oTarget = ai_GetEnemyAttackingMe(oCreature);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
|
||||
if(ai_TrySneakAttack(oCreature, nInMelee)) return;
|
||||
if(ai_TryWhirlwindFeat(oCreature)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ************************** Melee feat attacks *************************
|
||||
@@ -102,7 +125,12 @@ void main()
|
||||
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);
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
|
||||
@@ -63,19 +63,21 @@ void main()
|
||||
// ************************* MELEE ATTACKS *******************************
|
||||
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
|
||||
oTarget = ai_GetNearestTargetForMeleeCombat (oCreature, nInMelee);
|
||||
if (oTarget != OBJECT_INVALID)
|
||||
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_RIGHTHAND) == OBJECT_INVALID)
|
||||
{
|
||||
if (GetItemInSlot (INVENTORY_SLOT_CWEAPON_L) != OBJECT_INVALID)
|
||||
// If they don't have a claw then we need to do a special attack instead.
|
||||
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);
|
||||
SetLocalObject(oCreature, AI_ATTACKED_PHYSICAL, oTarget);
|
||||
}
|
||||
else ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
}
|
||||
else ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,30 @@ void main()
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
|
||||
else
|
||||
{
|
||||
if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
|
||||
oTarget = ai_GetEnemyAttackingMe(oCreature);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
|
||||
if(ai_TrySneakAttack(oCreature, nInMelee)) return;
|
||||
if(ai_TryWhirlwindFeat(oCreature)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ************************** Melee feat attacks *************************
|
||||
object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST);
|
||||
@@ -90,7 +113,12 @@ void main()
|
||||
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
|
||||
if(ai_TrySneakAttack(oCreature, nInMelee)) return;
|
||||
if(ai_TryWhirlwindFeat(oCreature)) return;
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
int StartingUp(object oPC);
|
||||
json ai_CheckToReplaceSpell(json jSpellList, int nClass, int nLevel, int nSlot)
|
||||
{
|
||||
//if(d100() > 49) return jSpellList;
|
||||
if(d100() > 49) return jSpellList;
|
||||
string sSpellTableColumn = Get2DAString("classes", "SpellTableColumn", nClass);
|
||||
int nRoll = d10() + 1 + nLevel * 10;
|
||||
int nSpell = StringToInt(Get2DAString("prc_add_spells", sSpellTableColumn, nRoll));
|
||||
|
||||
@@ -35,6 +35,7 @@ void main()
|
||||
}
|
||||
}
|
||||
// Send the user-defined event signal if specified here so it doesn't get skipped.
|
||||
//SendMessageToPC(GetFirstPC(), "HB_EVENT: " + IntToString(GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT)));
|
||||
if(GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT))
|
||||
{
|
||||
SignalEvent(oCreature, EventUserDefined(EVENT_HEARTBEAT));
|
||||
@@ -76,17 +77,9 @@ void main()
|
||||
ai_ClearBuffTargets(oCreature, "AI_ALLY_TARGET_");
|
||||
}
|
||||
}
|
||||
if(!IsInConversation (oCreature))
|
||||
{
|
||||
if(GetWalkCondition(NW_WALK_FLAG_CONSTANT)) WalkWayPoints();
|
||||
if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS)) PlayMobileAmbientAnimations_NonAvian();
|
||||
else if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN)) PlayMobileAmbientAnimations_Avian();
|
||||
else if(GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS)) PlayImmobileAmbientAnimations();
|
||||
else if(GetLocalInt(GetModule(), AI_RULE_WANDER) && GetStandardFactionReputation(STANDARD_FACTION_HOSTILE, oCreature) > 89)
|
||||
{
|
||||
ai_AmbientAnimations();
|
||||
}
|
||||
}
|
||||
if(ai_TryHealing(oCreature, oCreature)) return;
|
||||
// This is where PEPS passes control to either the Bioware Waypoint system and
|
||||
// AmbientAnimation scripts. A Persistent World can write there own scripts in 0e_animations.
|
||||
ExecuteScript("0e_animations", oCreature);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ void main()
|
||||
" Current action: " + IntToString(GetCurrentAction(oCreature)));
|
||||
if(GetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT))
|
||||
{
|
||||
SignalEvent(OBJECT_SELF, EventUserDefined(1003));
|
||||
SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_END_COMBAT_ROUND));
|
||||
}
|
||||
if(ai_Disabled(oCreature)) return;
|
||||
// Action modes get cleared prior to each OnCombatRoundEnd!
|
||||
|
||||
@@ -59,6 +59,8 @@ void main()
|
||||
string sAssociateType = ai_GetAssociateType(oMaster, oCreature);
|
||||
ai_CheckAssociateData(oMaster, oCreature, sAssociateType);
|
||||
ai_CheckPCStart(oMaster);
|
||||
// When a henchman dies and is brought back the plot flag can be set to TRUE!
|
||||
SetPlotFlag(oCreature, FALSE);
|
||||
if(AI_HENCHMAN_WIDGET)
|
||||
{
|
||||
// This keeps widgets from disappearing and reappearing.
|
||||
|
||||
@@ -37,6 +37,14 @@ void main()
|
||||
case ACTION_CASTSPELL :
|
||||
case ACTION_ITEMCASTSPELL :
|
||||
case ACTION_COUNTERSPELL : return;
|
||||
case ACTION_ATTACKOBJECT :
|
||||
{
|
||||
if(!ai_GetIsInCombat(oCreature))
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Might be doing a special action that is not a defined action.
|
||||
case ACTION_INVALID :
|
||||
{
|
||||
|
||||
@@ -26,77 +26,82 @@ json GetBuffDatabaseJson(object oPlayer, string sDataField, string sTag = "");
|
||||
// Returns the level if this spell has a domain spell on nLevel, or 0.
|
||||
int GetHasDomainSpell(object oCaster, int nClass, int nLevel, int nSpell);
|
||||
|
||||
// We do some crazy hack to get all the correct information when casting spells.
|
||||
// GetLastSpellCastClass() will only give the class if this script is running
|
||||
// on the actual caster, i.e. our PC.
|
||||
// GetLastSpellLevel() will only give the level if this script is running on
|
||||
// the actual caster, i.e. our PC.
|
||||
// So for this to work we run this scrip in the event OnSpellCastAt of our
|
||||
// target, then we ExecuteScript this script again with the Caster (oPC)
|
||||
// as OBJECT_SELF for this script on its second pass. This allows us to get the
|
||||
// information from the above functions! Neat!
|
||||
void main()
|
||||
{
|
||||
object oTarget = OBJECT_SELF;
|
||||
// The first pass we get oCaster via GetLastSpellCaster() fails in ExecuteScript!
|
||||
// The second pass we get oCaster via the variable "AI_BUFF_CASTER".
|
||||
object oCaster = GetLocalObject(oTarget, "AI_BUFF_CASTER");
|
||||
if(oCaster == OBJECT_INVALID) oCaster = GetLastSpellCaster();
|
||||
// We setting up the save spells button we saved the PC to itself.
|
||||
// Here we get the PC to make sure the caster of this spell is our saving PC.
|
||||
object oPC = GetLocalObject(oCaster, "AI_BUFF_PC");
|
||||
// The first pass we get nspell via GetLastSpell() fails in ExecuteScript!
|
||||
// The second pass we get nSpell via the variable "AI_BUFF_SPELL".
|
||||
int nSpell = GetLocalInt(oTarget, "AI_BUFF_SPELL");
|
||||
if(nSpell == 0) nSpell = GetLastSpell();
|
||||
// If this is a harful spell or The caster does not equal our saving PC then
|
||||
// we need to fix the targets scripts back and run the correct OnSpellCastAt script.
|
||||
if(GetLastSpellHarmful() || oPC != oCaster)
|
||||
object oCaster = GetLastSpellCaster();
|
||||
// When setting up the save spells button we saved the PC to itself.
|
||||
// Here we get the PC from either our henchmen or ourselves.
|
||||
// We do this to make sure that this PC and henchmen are the ones saving spells.
|
||||
object oPC = GetLocalObject(ai_GetPlayerMaster(oCaster), "AI_BUFF_PC");
|
||||
// If this is a harmful spell or we couldn't find oPC then we need to fix
|
||||
// the targets scripts back and run the correct OnSpellCastAt script.
|
||||
if(GetLastSpellHarmful() || oPC == OBJECT_INVALID)
|
||||
{
|
||||
string sScript = GetLocalString(oTarget, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript);
|
||||
DeleteLocalObject(oPC, "AI_BUFF_PC");
|
||||
string sScript = GetLocalString(oPC, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
SetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript);
|
||||
DeleteLocalString(oPC, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
// Cleanup your followers to allow spells to be reacted to as normal.
|
||||
int nAssociateType = 2;
|
||||
object oAssociate = GetAssociate(nAssociateType, oPC);
|
||||
while(nAssociateType < 5)
|
||||
{
|
||||
if(oAssociate != OBJECT_INVALID)
|
||||
{
|
||||
sScript = GetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript);
|
||||
DeleteLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
}
|
||||
oAssociate = GetAssociate(++nAssociateType, oPC);
|
||||
}
|
||||
int nIndex = 1;
|
||||
oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
|
||||
while(nIndex <= AI_MAX_HENCHMAN)
|
||||
{
|
||||
if(oAssociate != OBJECT_INVALID)
|
||||
{
|
||||
sScript = GetLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, sScript);
|
||||
DeleteLocalString(oAssociate, "AI_BUFF_CAST_AT_SCRIPT");
|
||||
}
|
||||
oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, ++nIndex);
|
||||
}
|
||||
NuiSetBind(oPC, NuiFindWindow(oPC, "widgetbuffwin"), "btn_save", JsonBool(FALSE));
|
||||
ai_SendMessages("Saving spells to the list has been turned off.", AI_COLOR_YELLOW, oPC);
|
||||
ExecuteScript(sScript, oTarget);
|
||||
return;
|
||||
}
|
||||
// If the oTarget != oCaster then we are casting a spell on one of our
|
||||
// associates. We must make a second pass to get the correct information.
|
||||
// We do this by saving the Target, Caster, and Spell so we can get them
|
||||
// in the second pass as Execute Script makes them impossible to get on a
|
||||
// second pass.
|
||||
if(oTarget != oCaster)
|
||||
{
|
||||
// if it is an area of effect spell then we skip it on all but the caster.
|
||||
if(Get2DAString("spells", "TargetShape", nSpell) == "")
|
||||
{
|
||||
SetLocalObject(oPC, "AI_BUFF_TARGET", oTarget);
|
||||
SetLocalObject(oPC, "AI_BUFF_CASTER", oCaster);
|
||||
SetLocalInt(oPC, "AI_BUFF_SPELL", nSpell);
|
||||
ExecuteScript("pc_savebuffs", oPC);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// If this is the first pass and we get here then oCaster is casting a spell
|
||||
// on themselves. So oTarget will be invalid and we should use oPC.
|
||||
// If this is the second pass and we get here then we have saved oTarget
|
||||
// to oPC and this will get them so we can save the target to the spell!
|
||||
oTarget = GetLocalObject(oPC, "AI_BUFF_TARGET");
|
||||
if(oTarget == OBJECT_INVALID) oTarget = oPC;
|
||||
// We need to clean up this mess!
|
||||
DeleteLocalObject(oPC, "AI_BUFF_TARGET");
|
||||
DeleteLocalObject(oPC, "AI_BUFF_CASTER");
|
||||
DeleteLocalInt(oPC, "AI_BUFF_SPELL");
|
||||
// This blocks one spell from saving multiple times due to being an AOE.
|
||||
if(GetLocalInt(oPC, "AI_ONLY_ONE")) return;
|
||||
SetLocalInt(oPC, "AI_ONLY_ONE", TRUE);
|
||||
// We delay this for just less than half a round due to haste.
|
||||
DelayCommand(2.5, DeleteLocalInt(oPC, "AI_ONLY_ONE"));
|
||||
// Here is the whole problem and why we must do a second pass if the target
|
||||
// is not the caster. These only work if this script is run by the caster.
|
||||
int nClass = GetLastSpellCastClass();
|
||||
int nLevel = GetLastSpellLevel();
|
||||
// Everything below saves the spell to the database with all our now correct info.
|
||||
int nDomain = GetHasDomainSpell(oPC, nClass, nLevel, nSpell);
|
||||
int nMetaMagic = GetMetaMagicFeat();
|
||||
// If the oTarget != oCaster then we are casting a spell on one of our
|
||||
// associates. Some functions expect OBJECT_SELF to be the caster.
|
||||
// We get around that by doing some ExecuteScriptChunk shenanigans.
|
||||
int nClass, nLevel, nMetaMagic;
|
||||
if(oTarget != oCaster)
|
||||
{
|
||||
// These functions need the caster to be OBJECT_SELF so lets do a HACK!
|
||||
ExecuteScriptChunk("SetLocalInt(OBJECT_SELF, \"AI_BUFF_CASTCLASS\", GetLastSpellCastClass());", oCaster);
|
||||
ExecuteScriptChunk("SetLocalInt(OBJECT_SELF, \"AI_BUFF_SPELLLEVEL\", GetLastSpellLevel());", oCaster);
|
||||
ExecuteScriptChunk("SetLocalInt(OBJECT_SELF, \"AI_BUFF_METAMAGIC\", GetMetaMagicFeat());", oCaster);
|
||||
nClass = GetLocalInt(oCaster, "AI_BUFF_CASTCLASS");
|
||||
nLevel = GetLocalInt(oCaster, "AI_BUFF_SPELLLEVEL");
|
||||
nMetaMagic = GetLocalInt(oCaster, "AI_METAMAGIC");
|
||||
DeleteLocalInt(oCaster, "AI_BUFF_CASTCLASS");
|
||||
DeleteLocalInt(oCaster, "AI_BUFF_SPELLLEVEL");
|
||||
DeleteLocalInt(oCaster, "AI_BUFF_METAMAGIC");
|
||||
}
|
||||
else
|
||||
{
|
||||
nClass = GetLastSpellCastClass();
|
||||
nLevel = GetLastSpellLevel();
|
||||
nMetaMagic = GetMetaMagicFeat();
|
||||
}
|
||||
int nSpell = GetLastSpell();
|
||||
int nDomain = GetHasDomainSpell(oCaster, nClass, nLevel, nSpell);
|
||||
string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
if(nDomain) sName += " [Domain]";
|
||||
if(nMetaMagic > 0 && StringToInt(Get2DAString("classes", "MemorizesSpells", nClass)))
|
||||
@@ -118,11 +123,13 @@ void main()
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nLevel));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nMetaMagic));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nDomain));
|
||||
string sCasterName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oCaster)));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonString(sCasterName));
|
||||
string sTargetName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oTarget)));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonString(sTargetName));
|
||||
jSpells = JsonArrayInsert(jSpells, jSpell);
|
||||
SetBuffDatabaseJson(oPC, "spells", jSpells, sList);
|
||||
SendMessageToPC(oPC, sName + " has been saved for fast buffing on " + sTargetName + ".");
|
||||
SendMessageToPC(oPC, sCasterName + " has cast " + sName + " to be saved for fast buffing on " + sTargetName + ".");
|
||||
ExecuteScript("pi_buffing", oPC);
|
||||
}
|
||||
string GetBuffDatabaseString(object oPlayer, string sDataField, string sTag)
|
||||
|
||||
@@ -45,24 +45,22 @@ void main()
|
||||
// Watch to see if the window moves and save.
|
||||
if(sElem == "window_geometry" && sEvent == "watch")
|
||||
{
|
||||
if(!GetLocalInt (oPC, AI_NO_NUI_SAVE))
|
||||
if(GetLocalInt (oPC, AI_NO_NUI_SAVE)) return;
|
||||
// Get the height, width, x, and y of the window.
|
||||
json jGeom = NuiGetBind(oPC, nToken, "window_geometry");
|
||||
// Save on the player using the sWndId.
|
||||
json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata");
|
||||
if(sWndId == "plbuffwin")
|
||||
{
|
||||
// Get the height, width, x, and y of the window.
|
||||
json jGeom = NuiGetBind(oPC, nToken, "window_geometry");
|
||||
// Save on the player using the sWndId.
|
||||
json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata");
|
||||
if(sWndId == "plbuffwin")
|
||||
{
|
||||
jMenuData = JsonArraySet(jMenuData, 1, JsonObjectGet(jGeom, "x"));
|
||||
jMenuData = JsonArraySet(jMenuData, 2, JsonObjectGet(jGeom, "y"));
|
||||
}
|
||||
else if(sWndId == "widgetbuffwin")
|
||||
{
|
||||
jMenuData = JsonArraySet(jMenuData, 5, JsonObjectGet(jGeom, "x"));
|
||||
jMenuData = JsonArraySet(jMenuData, 6, JsonObjectGet(jGeom, "y"));
|
||||
}
|
||||
SetBuffDatabaseJson(oPC, "spells", jMenuData, "menudata");
|
||||
jMenuData = JsonArraySet(jMenuData, 1, JsonObjectGet(jGeom, "x"));
|
||||
jMenuData = JsonArraySet(jMenuData, 2, JsonObjectGet(jGeom, "y"));
|
||||
}
|
||||
else if(sWndId == "widgetbuffwin")
|
||||
{
|
||||
jMenuData = JsonArraySet(jMenuData, 5, JsonObjectGet(jGeom, "x"));
|
||||
jMenuData = JsonArraySet(jMenuData, 6, JsonObjectGet(jGeom, "y"));
|
||||
}
|
||||
SetBuffDatabaseJson(oPC, "spells", jMenuData, "menudata");
|
||||
return;
|
||||
}
|
||||
//**************************************************************************
|
||||
@@ -175,6 +173,7 @@ void main()
|
||||
}
|
||||
else if(sEvent == "watch")
|
||||
{
|
||||
if(GetLocalInt (oPC, AI_NO_NUI_SAVE)) return;
|
||||
if(sElem == "buff_widget_check")
|
||||
{
|
||||
int bBuffWidget = JsonGetInt(NuiGetBind(oPC, nToken, "buff_widget_check"));
|
||||
@@ -184,7 +183,7 @@ void main()
|
||||
if(bBuffWidget) PopupWidgetBuffGUIPanel(oPC);
|
||||
else NuiDestroy(oPC, NuiFindWindow(oPC, "widgetbuffwin"));
|
||||
}
|
||||
if(sElem == "lock_buff_widget_check")
|
||||
else if(sElem == "lock_buff_widget_check")
|
||||
{
|
||||
int bBuffLockWidget = JsonGetInt(NuiGetBind(oPC, nToken, "lock_buff_widget_check"));
|
||||
json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata");
|
||||
@@ -194,11 +193,20 @@ void main()
|
||||
NuiSetBind(oPC, nToken, "buff_widget_check", JsonBool(TRUE));
|
||||
PopupWidgetBuffGUIPanel(oPC);
|
||||
}
|
||||
if(sElem == "chbx_no_monster_check_check")
|
||||
else if(sElem == "chbx_no_monster_check_check")
|
||||
{
|
||||
int bNoCheckMonsters = JsonGetInt(NuiGetBind(oPC, nToken, sElem));
|
||||
SetLocalInt(oPC, FB_NO_MONSTER_CHECK, bNoCheckMonsters);
|
||||
}
|
||||
else if(sElem == "txt_spell_delay")
|
||||
{
|
||||
string sDelay = JsonGetString(NuiGetBind(oPC, nToken, "txt_spell_delay"));
|
||||
float fDelay = StringToFloat(sDelay);
|
||||
if(fDelay < 0.1f) fDelay = 0.1f;
|
||||
if(fDelay > 6.0f) fDelay = 6.0f;
|
||||
sDelay = FloatToString(fDelay, 0, 1);
|
||||
SetBuffDatabaseString(oPC, "spells", sDelay, "Delay");
|
||||
}
|
||||
}
|
||||
}
|
||||
//**************************************************************************
|
||||
@@ -259,13 +267,12 @@ json GetBuffDatabaseJson (object oPlayer, string sDataField, string sTag)
|
||||
if(SqlStep(sql)) return SqlGetJson(sql, 0);
|
||||
else return JsonArray();
|
||||
}
|
||||
void CastBuffSpell (object oPC, object oTarget, int nSpell, int nClass, int nMetamagic, int nDomain, string sList, string sName)
|
||||
void CastBuffSpell(object oPC, object oCaster, object oTarget, int nSpell, int nClass, int nMetamagic, int nDomain, string sList, string sName, int bInstantSpell)
|
||||
{
|
||||
string sTargetName;
|
||||
if(oPC == oTarget) sTargetName = "myself.";
|
||||
else sTargetName = GetName(oTarget);
|
||||
ai_SendMessages("Quick Buffing: " + sName + " on " + sTargetName, AI_COLOR_GREEN, oPC);
|
||||
AssignCommand(oPC, ActionCastSpellAtObject(nSpell, oTarget, nMetamagic, FALSE, nDomain, 0, TRUE, nClass));
|
||||
string sCasterName = GetName(oCaster);
|
||||
string sTargetName = GetName(oTarget);
|
||||
ai_SendMessages(sCasterName + " is quick buffing " + sName + " on " + sTargetName, AI_COLOR_GREEN, oPC);
|
||||
AssignCommand(oCaster, ActionCastSpellAtObject(nSpell, oTarget, nMetamagic, FALSE, nDomain, 0, bInstantSpell, nClass));
|
||||
}
|
||||
void CastSavedBuffSpells(object oPC)
|
||||
{
|
||||
@@ -314,7 +321,10 @@ void CastSavedBuffSpells(object oPC)
|
||||
if(fDistance > 30.0f || fDistance == 0.0)
|
||||
{
|
||||
string sName;
|
||||
float fDelay = 0.1f;
|
||||
float fDelay;
|
||||
float fDelayIncrement = StringToFloat(GetBuffDatabaseString(oPC, "spells", "Delay"));;
|
||||
int bInstantSpell;
|
||||
if(fDelayIncrement < 3.0f) bInstantSpell = TRUE;
|
||||
int nSpell, nClass, nLevel, nMetamagic, nDomain, nSpellReady, nIndex = 0;
|
||||
json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata");
|
||||
string sList = JsonGetString(JsonArrayGet(jMenuData, 0));
|
||||
@@ -329,58 +339,78 @@ void CastSavedBuffSpells(object oPC)
|
||||
nLevel = JsonGetInt(JsonArrayGet(jSpell, 2));
|
||||
nMetamagic = JsonGetInt(JsonArrayGet(jSpell, 3));
|
||||
nDomain = JsonGetInt(JsonArrayGet(jSpell, 4));
|
||||
// We save the target's name then look them up by it.
|
||||
string sTargetName = JsonGetString(JsonArrayGet(jSpell, 5));
|
||||
object oTarget;
|
||||
location lLocation = GetLocation(oPC);
|
||||
if(sTargetName == "" || sTargetName == ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPC)))) oTarget = oPC;
|
||||
else
|
||||
{
|
||||
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 20.0, lLocation, TRUE);
|
||||
while(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(sTargetName == ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oTarget)))) break;
|
||||
oTarget = GetNextObjectInShape(SHAPE_SPHERE, 20.0, lLocation, TRUE);
|
||||
}
|
||||
}
|
||||
sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
location lLocation = GetLocation(oPC);
|
||||
// Saved the Caster's name so we can find them to cast the spell.
|
||||
string sCasterName = JsonGetString(JsonArrayGet(jSpell, 5));
|
||||
object oCaster;
|
||||
if(sCasterName == "" || sCasterName == ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPC)))) oCaster = oPC;
|
||||
else
|
||||
{
|
||||
DelayCommand(fDelay, ai_SendMessages("Cannot quick cast " + sName + " because the " + sTargetName + " is not here!", AI_COLOR_RED, oPC));
|
||||
oCaster = GetFirstObjectInShape(SHAPE_SPHERE, 20.0, lLocation, TRUE);
|
||||
while(oCaster != OBJECT_INVALID)
|
||||
{
|
||||
if(sCasterName == ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oCaster)))) break;
|
||||
oCaster = GetNextObjectInShape(SHAPE_SPHERE, 20.0, lLocation, TRUE);
|
||||
}
|
||||
}
|
||||
if(oCaster == OBJECT_INVALID)
|
||||
{
|
||||
DelayCommand(fDelay, ai_SendMessages("Cannot quick cast " + sName + " because the " + sCasterName + " is not here!", AI_COLOR_RED, oPC));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(nMetamagic > 0)
|
||||
// Saved the target's name so we can find them to cast the spell on.
|
||||
string sTargetName = JsonGetString(JsonArrayGet(jSpell, 6));
|
||||
object oTarget;
|
||||
if(sTargetName == "" || sTargetName == ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPC)))) oTarget = oPC;
|
||||
else
|
||||
{
|
||||
if(nMetamagic == METAMAGIC_EMPOWER) sName += " (Empowered)";
|
||||
else if(nMetamagic == METAMAGIC_EXTEND) sName += " (Extended)";
|
||||
else if(nMetamagic == METAMAGIC_MAXIMIZE) sName += " (Maximized)";
|
||||
else if(nMetamagic == METAMAGIC_QUICKEN) sName += " (Quickened)";
|
||||
else if(nMetamagic == METAMAGIC_SILENT) sName += " (Silent)";
|
||||
else if(nMetamagic == METAMAGIC_STILL) sName += " (Still)";
|
||||
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 20.0, lLocation, TRUE);
|
||||
while(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(sTargetName == ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oTarget)))) break;
|
||||
oTarget = GetNextObjectInShape(SHAPE_SPHERE, 20.0, lLocation, TRUE);
|
||||
}
|
||||
}
|
||||
nSpellReady = GetSpellReady(oPC, nSpell, nClass, nLevel, nMetamagic, nDomain);
|
||||
if(nSpellReady == TRUE)
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
DelayCommand(fDelay, CastBuffSpell(oPC, oTarget, nSpell, nClass, nMetamagic, nDomain, sList, sName));
|
||||
DelayCommand(fDelay, ai_SendMessages("Cannot quick cast " + sName + " because the " + sTargetName + " is not here!", AI_COLOR_RED, oPC));
|
||||
}
|
||||
else if(nSpellReady == -1)
|
||||
else
|
||||
{
|
||||
DelayCommand(fDelay, ai_SendMessages("Cannot quick cast " + sName + " because it is not ready to cast!", AI_COLOR_RED, oPC));
|
||||
if(nMetamagic > 0)
|
||||
{
|
||||
if(nMetamagic == METAMAGIC_EMPOWER) sName += " (Empowered)";
|
||||
else if(nMetamagic == METAMAGIC_EXTEND) sName += " (Extended)";
|
||||
else if(nMetamagic == METAMAGIC_MAXIMIZE) sName += " (Maximized)";
|
||||
else if(nMetamagic == METAMAGIC_QUICKEN) sName += " (Quickened)";
|
||||
else if(nMetamagic == METAMAGIC_SILENT) sName += " (Silent)";
|
||||
else if(nMetamagic == METAMAGIC_STILL) sName += " (Still)";
|
||||
}
|
||||
nSpellReady = GetSpellReady(oCaster, nSpell, nClass, nLevel, nMetamagic, nDomain);
|
||||
if(nSpellReady == TRUE)
|
||||
{
|
||||
DelayCommand(fDelay, CastBuffSpell(oPC, oCaster, oTarget, nSpell, nClass, nMetamagic, nDomain, sList, sName, bInstantSpell));
|
||||
}
|
||||
else if(nSpellReady == -1)
|
||||
{
|
||||
DelayCommand(fDelay, ai_SendMessages(sCasterName + " cannot quick cast " + sName + " because it is not ready to cast!", AI_COLOR_RED, oPC));
|
||||
}
|
||||
else if(nSpellReady == -2)
|
||||
{
|
||||
DelayCommand (fDelay, ai_SendMessages(sCasterName + " cannot quick cast " + sName + " because it is not memorized!", AI_COLOR_RED, oPC));
|
||||
}
|
||||
else if(nSpellReady == -3)
|
||||
{
|
||||
DelayCommand (fDelay, ai_SendMessages(sCasterName + " cannot quick cast " + sName + " because there are no spell slots of that level left!", AI_COLOR_RED, oPC));
|
||||
}
|
||||
else if(nSpellReady == -4)
|
||||
{
|
||||
DelayCommand (fDelay, ai_SendMessages(sCasterName + "cannot quick cast " + sName + " because that spell is not known.", AI_COLOR_RED, oPC));
|
||||
}
|
||||
fDelay += fDelayIncrement;
|
||||
}
|
||||
else if(nSpellReady == -2)
|
||||
{
|
||||
DelayCommand (fDelay, ai_SendMessages("Cannot quick cast " + sName + " because it is not memorized!", AI_COLOR_RED, oPC));
|
||||
}
|
||||
else if(nSpellReady == -3)
|
||||
{
|
||||
DelayCommand (fDelay, ai_SendMessages("Cannot quick cast " + sName + " because there are no spell slots of that level left!", AI_COLOR_RED, oPC));
|
||||
}
|
||||
else if(nSpellReady == -4)
|
||||
{
|
||||
DelayCommand (fDelay, ai_SendMessages("Cannot quick cast " + sName + " because that spell is not known.", AI_COLOR_RED, oPC));
|
||||
}
|
||||
fDelay += 0.1f;
|
||||
}
|
||||
}
|
||||
else break;
|
||||
@@ -519,7 +549,6 @@ void PopupWidgetBuffGUIPanel(object oPC)
|
||||
if(bAIBuffWidgetLock) nToken = SetWindow (oPC, jLayout, "widgetbuffwin", "Fast Buff Widget", fX, fY, 160.0, 62.0, FALSE, FALSE, FALSE, TRUE, FALSE, "pe_buffing");
|
||||
else nToken = SetWindow (oPC, jLayout, "widgetbuffwin", "Fast Buff Widget", fX, fY, 160.0, 95.0, FALSE, FALSE, FALSE, TRUE, TRUE, "pe_buffing");
|
||||
// Set event watches for window inspector and save window location.
|
||||
NuiSetBindWatch (oPC, nToken, "collapsed", TRUE);
|
||||
NuiSetBindWatch (oPC, nToken, "window_geometry", TRUE);
|
||||
// Set the buttons to show events.
|
||||
//NuiSetBind (oPC, nToken, "btn_one", JsonBool (TRUE));
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
#include "nw_inc_gff"
|
||||
#include "0i_main"
|
||||
#include "0i_items"
|
||||
// Banned list of BaseItemTypes use rows from baseitemtype.2da.
|
||||
// Place each one between a : . Example ":21:28:" will not change belts and clubs.
|
||||
// Best used for visual effect items like helms.
|
||||
const string CRAFT_BANNED_BASEITEMTYPES = ":23:";
|
||||
//const string CRAFT_BANNED_BASEITEMTYPES = "::";
|
||||
// Maximum model number for all items except weapons.
|
||||
const int CRAFT_MAX_MODEL_NUMBER = 999;
|
||||
|
||||
@@ -100,6 +105,8 @@ void CraftItemInfoEvents(object oPC, int nToken);
|
||||
json CreateItemCombo(object oPC, json jRow, string sComboBind);
|
||||
json CreateModelCombo(object oPC, object oTarget, json jRow, string sComboBind);
|
||||
void CreateCreatureCraftingGUIPanel(object oPC, object oTarget);
|
||||
// See above for constant that can have base item types added to the list.
|
||||
int IfOnBannedBaseItemTypeList(object oPC, object oItem);
|
||||
|
||||
int GetColorIDChange(object oItem, int nType, int nIndex, int nChange)
|
||||
{
|
||||
@@ -131,7 +138,7 @@ void main()
|
||||
int nObjectType = GetObjectType(oTarget);
|
||||
if(nObjectType == OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
if(ai_GetIsCharacter(oTarget) || GetMaster(oTarget) == oPC ||
|
||||
if(oPC == oTarget || GetMaster(oTarget) == oPC ||
|
||||
ai_GetIsDungeonMaster(oPC))
|
||||
{
|
||||
SetLocalObject(oPC, CRAFT_TARGET, oTarget);
|
||||
@@ -1238,6 +1245,8 @@ object ChangeItemsAppearance(object oPC, object oTarget, int nToken, object oIte
|
||||
// " nModelSelected: " + IntToString(nModelSelected));
|
||||
}
|
||||
// Change the model.
|
||||
//WriteTimestampedLogEntry("pe_crafting, 1241, " + GetName(oItem) + " nModelSelected: " +
|
||||
// IntToString(nModelSelected) + " nModelNumber: " + IntToString(nModelNumber));
|
||||
oNewItem = CopyItemAndModify (oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nModelSelected, nModelNumber, TRUE);
|
||||
DestroyObject (oItem);
|
||||
AssignCommand (oTarget, ActionEquipItem (oNewItem, INVENTORY_SLOT_CHEST));
|
||||
@@ -1270,6 +1279,8 @@ object ChangeItemsAppearance(object oPC, object oTarget, int nToken, object oIte
|
||||
// Note: Right Thigh and Left Thigh are backwards so this fixes that!
|
||||
if (nModelSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nModelSelected--;
|
||||
else nModelSelected++;
|
||||
//WriteTimestampedLogEntry("pe_crafting, 1275, " + GetName(oItem) + " nModelSelected: " +
|
||||
// IntToString(nModelSelected) + " nModelNumber: " + IntToString(nModelNumber));
|
||||
oItem = CopyItemAndModify(oNewItem, ITEM_APPR_TYPE_ARMOR_MODEL, nModelSelected, nModelNumber, TRUE);
|
||||
DestroyObject(oNewItem);
|
||||
AssignCommand(oTarget, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST));
|
||||
@@ -1586,6 +1597,7 @@ void SaveCraftedItem(object oPC, object oTarget, int nToken)
|
||||
}
|
||||
int CanCraftItem(object oPC, object oItem, int nToken, int bPasteCheck = FALSE)
|
||||
{
|
||||
if(IfOnBannedBaseItemTypeList(oPC, oItem)) return FALSE;
|
||||
// Plot items cannot be changed.
|
||||
if(GetPlotFlag(oItem))
|
||||
{
|
||||
@@ -2466,16 +2478,16 @@ void CreateCreatureCraftingGUIPanel(object oPC, object oTarget)
|
||||
jGroupRow = CreateLabel(JsonArray(), "Material to Color", "lbl_material_color", 320.0f, 10.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 556 (groups)********************************************************* 508 / 529 /352
|
||||
jGroupRow = CreateButtonSelect(JsonArray(), "Cloth 1", "btn_material_0", 98.0, 30.0);
|
||||
jGroupRow = CreateButtonSelect(JsonArray(), "Leather 1", "btn_material_0", 98.0, 30.0);
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "Leather 1", "btn_material_2", 98.0, 30.0);
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "Cloth 1", "btn_material_2", 98.0, 30.0);
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "Metal 1", "btn_material_4", 98.0, 30.0);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 557 (groups)********************************************************* 508 / 567 / 390
|
||||
jGroupRow = CreateButtonSelect(JsonArray(), "Cloth 2", "btn_material_1", 98.0, 30.0);
|
||||
jGroupRow = CreateButtonSelect(JsonArray(), "Leather 2", "btn_material_1", 98.0, 30.0);
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "Leather 2", "btn_material_3", 98.0, 30.0);
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "Cloth 2", "btn_material_3", 98.0, 30.0);
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "Metal 2", "btn_material_5", 98.0, 30.0);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
@@ -2855,4 +2867,18 @@ void CreateCreatureCraftingGUIPanel(object oPC, object oTarget)
|
||||
// Lets make sure we clean up any cool down variables.
|
||||
//DeleteLocalInt(oPC, CRAFT_COOL_DOWN);
|
||||
}
|
||||
|
||||
int IfOnBannedBaseItemTypeList(object oPC, object oItem)
|
||||
{
|
||||
int nIndex, nBaseItemType = GetBaseItemType(oItem);
|
||||
int nBannedBaseItemType = StringToInt(ai_GetStringArray(CRAFT_BANNED_BASEITEMTYPES, nIndex));
|
||||
while(nBannedBaseItemType)
|
||||
{
|
||||
if(nBaseItemType == nBannedBaseItemType)
|
||||
{
|
||||
ai_SendMessages(GetName(oItem) + " cannot have it's appearance changed!", AI_COLOR_RED, oPC);
|
||||
return TRUE;
|
||||
}
|
||||
nBannedBaseItemType = StringToInt(ai_GetStringArray(CRAFT_BANNED_BASEITEMTYPES, ++nIndex));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -57,13 +57,10 @@ void main()
|
||||
}
|
||||
ai_SendMessages("Your reputation with " + GetName(oTarget) + " has been set to neutral.", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
else if(sTargetMode == "SET_REPUTATION")
|
||||
else if(sTargetMode == "CLEAR_COMMANDABLE")
|
||||
{
|
||||
SetStandardFactionReputation(STANDARD_FACTION_COMMONER, 50, oTarget);
|
||||
SetStandardFactionReputation(STANDARD_FACTION_DEFENDER, 50, oTarget);
|
||||
SetStandardFactionReputation(STANDARD_FACTION_HOSTILE, 50, oTarget);
|
||||
SetStandardFactionReputation(STANDARD_FACTION_MERCHANT, 50, oTarget);
|
||||
ai_SendMessages(GetName(oTarget) + " has been set to a neutral reputation.", AI_COLOR_YELLOW, oPC);
|
||||
SetCommandable(TRUE, oTarget);
|
||||
ai_SendMessages(GetName(oTarget) + " has been set to be commandable.", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
else if(sTargetMode == "DEBUG_INFO")
|
||||
{
|
||||
@@ -78,6 +75,9 @@ void main()
|
||||
int nObjectType = GetObjectType(oTarget);
|
||||
if(nObjectType == OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
string sText = "Yes";
|
||||
if(!GetCommandable(oTarget)) sText = "No";
|
||||
ai_SendMessages("Commandable: " + sText, AI_COLOR_WHITE, oPC);
|
||||
json jObject = ObjectToJson(oTarget);
|
||||
string sConversation = JsonGetString(GffGetResRef(jObject, "Conversation"));
|
||||
ai_SendMessages("Conversation: " + sConversation, AI_COLOR_CYAN, oPC);
|
||||
@@ -509,14 +509,14 @@ void main()
|
||||
ai_SendMessages("Select an npc to change scripts for.", AI_COLOR_YELLOW, oPC);
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE , MOUSECURSOR_CREATE, MOUSECURSOR_NOCREATE);
|
||||
}
|
||||
else if(sElem == "btn_set_reputation")
|
||||
else if(sElem == "btn_set_commandable")
|
||||
{
|
||||
// Set this variable on the player so PEPS can run the targeting script for this plugin.
|
||||
SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_debug");
|
||||
// Set Targeting variables.
|
||||
SetLocalString(oPC, AI_TARGET_MODE, "SET_REPUTATION");
|
||||
SetLocalString(oPC, AI_TARGET_MODE, "CLEAR_COMMANDABLE");
|
||||
NuiDestroy(oPC, nToken);
|
||||
ai_SendMessages("Select a creature to set all standard reputations to neutral.", AI_COLOR_YELLOW, oPC);
|
||||
ai_SendMessages("Select a creature to set commandable.", AI_COLOR_YELLOW, oPC);
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE);
|
||||
}
|
||||
else if(sElem == "btn_clear_reputation")
|
||||
|
||||
@@ -37,6 +37,9 @@ void PopupWidgetBuffGUIPanel(object oPC);
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
// Set window to not save until it has been created.
|
||||
SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE);
|
||||
DelayCommand(0.5f, DeleteLocalInt(oPC, AI_NO_NUI_SAVE));
|
||||
// Check to make sure the database is setup before we do anything.
|
||||
CheckBuffDataAndInitialize(oPC, "menudata");
|
||||
json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata");
|
||||
@@ -60,6 +63,7 @@ void main()
|
||||
jRow = CreateButtonSelect(jRow, "List 2", "btn_list2", 60.0f, 30.0f);
|
||||
jRow = CreateButtonSelect(jRow, "List 3", "btn_list3", 60.0f, 30.0f);
|
||||
jRow = CreateButtonSelect(jRow, "List 4", "btn_list4", 60.0f, 30.0f);
|
||||
jRow = CreateTextEditBox(jRow, "", "txt_spell_delay", 3, FALSE, 40.0f, 30.0f, "txt_spell_delay_tooltip");
|
||||
// Add the row to the column.
|
||||
json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow));
|
||||
// Row 2 (Buttons) ********************************************************* 121
|
||||
@@ -103,7 +107,7 @@ void main()
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Get the window location to restore it from the database.
|
||||
float fWidth = IntToFloat(nIndex) * 39;
|
||||
if(fWidth < 470.0) fWidth = 470.0;
|
||||
if(fWidth < 530.0) fWidth = 530.0;
|
||||
float fX = JsonGetFloat(JsonArrayGet(jMenuData, 1));
|
||||
float fY = JsonGetFloat(JsonArrayGet(jMenuData, 2));
|
||||
if(fX == 0.0f && fY == 0.0f)
|
||||
@@ -115,6 +119,8 @@ void main()
|
||||
json jLayout = NuiCol(jCol);
|
||||
int nToken = SetWindow(oPC, jLayout, "plbuffwin", "Fast Buffing Spells",
|
||||
fX, fY, fWidth, 164.0, FALSE, FALSE, TRUE, FALSE, TRUE, "pe_buffing");
|
||||
// Set event watches for window inspector and save window location.
|
||||
NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE);
|
||||
// Set the elements to show events.
|
||||
int nSelected = GetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT) == "pc_savebuffs";
|
||||
NuiSetBind(oPC, nToken, "btn_save", JsonBool(nSelected));
|
||||
@@ -138,11 +144,22 @@ void main()
|
||||
if(sList == "list4") NuiSetBind (oPC, nToken, "btn_list4", JsonBool (TRUE));
|
||||
else NuiSetBind (oPC, nToken, "btn_list4", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_list4_event", JsonBool(TRUE));
|
||||
NuiSetBindWatch(oPC, nToken, "txt_spell_delay", TRUE);
|
||||
string sText = " Allows you to adjust the speed that spells are cast in [0.1 seconds to 6.0 seconds]";
|
||||
NuiSetBind(oPC, nToken, "txt_spell_delay_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_spell_delay_tooltip", JsonString(sText));
|
||||
CheckBuffDataAndInitialize(oPC, "Delay");
|
||||
sText = GetBuffDatabaseString(oPC, "spells", "Delay");
|
||||
float fDelay = StringToFloat(sText);
|
||||
if(fDelay < 0.1f) fDelay = 0.1f;
|
||||
else if(fDelay > 6.0f) fDelay = 6.0f;
|
||||
sText = FloatToString(fDelay, 0, 1);
|
||||
NuiSetBind(oPC, nToken, "txt_spell_delay", JsonString(sText));
|
||||
int nValue = JsonGetInt(JsonArrayGet(jMenuData, 3));
|
||||
NuiSetBind(oPC, nToken, "buff_widget_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "buff_widget_check", JsonBool(nValue));
|
||||
NuiSetBindWatch(oPC, nToken, "buff_widget_check", TRUE);
|
||||
string sText = " Creates a set of 4 buttons on the screen for quick buffing.";
|
||||
sText = " Creates a set of 4 buttons on the screen for quick buffing.";
|
||||
NuiSetBind(oPC, nToken, "buff_widget_tooltip", JsonString(sText));
|
||||
nValue = JsonGetInt(JsonArrayGet(jMenuData, 4));
|
||||
NuiSetBind(oPC, nToken, "lock_buff_widget_event", JsonBool(TRUE));
|
||||
@@ -161,7 +178,7 @@ void main()
|
||||
}
|
||||
// Create buttons with spells listed.
|
||||
int nSpell, nClass, nLevel, nMetamagic, nDomain;
|
||||
string sName, sTargetName, sResRef;
|
||||
string sName, sTargetName, sCasterName, sResRef;
|
||||
nCntr = 0;
|
||||
nIndex = 0;
|
||||
while(nCntr <= BUFF_MAX_SPELLS)
|
||||
@@ -174,11 +191,13 @@ void main()
|
||||
nLevel = JsonGetInt(JsonArrayGet(jSpell, 2));
|
||||
nMetamagic = JsonGetInt(JsonArrayGet(jSpell, 3));
|
||||
nDomain = JsonGetInt(JsonArrayGet(jSpell, 4));
|
||||
sTargetName = JsonGetString(JsonArrayGet(jSpell, 5));
|
||||
sCasterName = JsonGetString(JsonArrayGet(jSpell, 5));
|
||||
sTargetName = JsonGetString(JsonArrayGet(jSpell, 6));
|
||||
sResRef = Get2DAString("spells", "IconResRef", nSpell);
|
||||
sName = " " + GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
sName += " (" + GetStringByStrRef(StringToInt(Get2DAString("classes", "Short", nClass)));
|
||||
sName += " / " + IntToString (nLevel);
|
||||
sName = " " + sCasterName + " (";
|
||||
sName += GetStringByStrRef(StringToInt(Get2DAString("classes", "Short", nClass)));
|
||||
sName += " / " + IntToString (nLevel) + ") casting ";
|
||||
sName += GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
if(nMetamagic > 0)
|
||||
{
|
||||
if(nMetamagic == METAMAGIC_EMPOWER) sName += " / Empowered";
|
||||
@@ -189,7 +208,7 @@ void main()
|
||||
else if(nMetamagic == METAMAGIC_STILL) sName += " / Still";
|
||||
}
|
||||
if(nDomain > 0) sName += " / Domain";
|
||||
sName += ") " + sTargetName;
|
||||
sName += " on " + sTargetName;
|
||||
sIndex = IntToString(nIndex++);
|
||||
NuiSetBind(oPC, nToken, "btn_spell_" + sIndex + "_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_spell_" + sIndex + "_image", JsonString(sResRef));
|
||||
@@ -197,7 +216,6 @@ void main()
|
||||
}
|
||||
nCntr++;
|
||||
}
|
||||
NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE);
|
||||
}
|
||||
int StartingUp(object oPC)
|
||||
{
|
||||
|
||||
@@ -54,7 +54,7 @@ void main()
|
||||
jRow = JsonArrayInsert(JsonArray(), NuiSpacer());
|
||||
jRow = CreateButton(jRow, "Set NPC's scripts", "btn_npc_scripts", 150.0f, 20.0f, -1.0, "btn_npc_scripts_tooltip");
|
||||
jRow = JsonArrayInsert(jRow, NuiSpacer());
|
||||
jRow = CreateButton(jRow, "Set Reputations", "btn_set_reputation", 150.0f, 20.0f, -1.0, "btn_set_reputation_tooltip");
|
||||
jRow = CreateButton(jRow, "Set Commandable", "btn_set_commandable", 150.0f, 20.0f, -1.0, "btn_set_commandable_tooltip");
|
||||
jRow = JsonArrayInsert(jRow, NuiSpacer());
|
||||
jRow = CreateButton(jRow, "Clear Party Rep.", "btn_clear_reputation", 150.0f, 20.0f, -1.0, "btn_clear_reputation_tooltip");
|
||||
jRow = JsonArrayInsert(jRow, NuiSpacer());
|
||||
@@ -152,8 +152,8 @@ void main()
|
||||
// Row 6
|
||||
NuiSetBind(oPC, nToken, "btn_npc_scripts_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_npc_scripts_tooltip", JsonString(" Forces NPC to use Philos AI scripts!"));
|
||||
NuiSetBind(oPC, nToken, "btn_set_reputation_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_set_reputation_tooltip", JsonString(" Sets a creatures faction to neutral for all standard factions."));
|
||||
NuiSetBind(oPC, nToken, "btn_set_commandable_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_set_commandable_tooltip", JsonString(" Sets a creatures to commandable."));
|
||||
NuiSetBind(oPC, nToken, "btn_clear_reputation_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_clear_reputation_tooltip", JsonString(" Clears the party's reputation with creature's faction."));
|
||||
// Row 7
|
||||
|
||||
@@ -419,11 +419,7 @@ void SaveYourHenchman(object oPC, int nToken, string sParty)
|
||||
if(sName == sHenchmanName || sName == "")
|
||||
{
|
||||
sSlot = sParty + sIndex;
|
||||
if(!bPC)
|
||||
{
|
||||
RemoveHenchman(oPC, oHenchman);
|
||||
ChangeToStandardFaction(oHenchman, STANDARD_FACTION_DEFENDER);
|
||||
}
|
||||
if(!bPC) RemoveHenchman(oPC, oHenchman);
|
||||
// Special check for Infinite Dungeon plot givers to be changed into henchman.
|
||||
if(GetStringLeft(GetLocalString(oHenchman, "sConversation"), 8) == "id1_plot")
|
||||
{
|
||||
@@ -438,6 +434,13 @@ void SaveYourHenchman(object oPC, int nToken, string sParty)
|
||||
// We need to make sure the henchman is not seen as a PC or DM!
|
||||
jHenchman = GffReplaceByte(jHenchman, "IsPC", 0);
|
||||
jHenchman = GffReplaceByte(jHenchman, "IsDM", 0);
|
||||
// Rename them with a number added to the end, helps tell the
|
||||
// difference between the PC and the new henchman.
|
||||
string sNameIndex, sLastName = JsonGetString(GffGetLocString(jHenchman, "LastName"));
|
||||
int nNameIndex = StringToInt(GetStringRight(sLastName, 1));
|
||||
if(nNameIndex > 0) GetStringLeft(sLastName, GetStringLength(sLastName) -1) + IntToString(nNameIndex++);
|
||||
else sNameIndex = "_1";
|
||||
jHenchman = GffReplaceLocString(jHenchman, "LastName", sLastName + "_");
|
||||
}
|
||||
CheckHenchmanDataAndInitialize(oPC, sSlot);
|
||||
SetHenchmanDbString(oPC, "image", GetPortraitResRef(oHenchman), sSlot);
|
||||
@@ -459,8 +462,8 @@ void SaveYourHenchman(object oPC, int nToken, string sParty)
|
||||
SetHenchmanDbString(oPC, "stats", sStats, sSlot);
|
||||
SetHenchmanDbString(oPC, "classes", sClasses, sSlot);
|
||||
SetHenchmanDbJson(oPC, "henchman", jHenchman, sSlot);
|
||||
if(sName == "") ai_SendMessages(sHenchmanName + " has been saved to the party.", AI_COLOR_GREEN, oPC);
|
||||
else ai_SendMessages(sHenchmanName + " has replaced a copy of themselves in the party.", AI_COLOR_GREEN, oPC);
|
||||
if(sName == "") ai_SendMessages(sHenchmanName + " has been saved to the party " + sParty + ".", AI_COLOR_GREEN, oPC);
|
||||
else ai_SendMessages(sHenchmanName + " has replaced a copy of themselves in the party " + sParty + ".", AI_COLOR_GREEN, oPC);
|
||||
break;
|
||||
}
|
||||
nIndex++;
|
||||
@@ -679,11 +682,8 @@ int GetSelectionByPackage2DA(string sClass, int nPackage)
|
||||
if(Get2DAString("packages", "ClassID", nIndex) == sClass)
|
||||
{
|
||||
sPackageName = GetStringByStrRef(StringToInt(Get2DAString("packages", "Name", nIndex)));
|
||||
//if(sPackageName != "Bad Strref" && sPackageName != "")
|
||||
//{
|
||||
if(nPackage == nIndex) return nSelection;
|
||||
nSelection++;
|
||||
//}
|
||||
if(nPackage == nIndex) return nSelection;
|
||||
nSelection++;
|
||||
}
|
||||
nIndex++;
|
||||
}
|
||||
@@ -821,7 +821,7 @@ json CreateLevelStatList(json jHenchman, object oHenchman, object oPC, int nLeve
|
||||
{
|
||||
jLevelArray = JsonArrayInsert(jLevelArray, jLevel);
|
||||
}
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 813, Creating LvlStatList for " + GetName(oHenchman));
|
||||
//WriteTimestampedLogEntry("pinc_henchmen, 813, Creating LvlStatList for " + GetName(oHenchman));
|
||||
return GffAddList(jHenchman, "LvlStatList", jLevelArray);
|
||||
}
|
||||
int GetHasJFeat(int nFeat, json jFeatList)
|
||||
@@ -1003,12 +1003,12 @@ json ResetFeats(json jHenchman, object oHenchman)
|
||||
jFeat = GffAddWord(jFeat, "Feat", nRaceFeat);
|
||||
jFeat = JsonObjectSet(jFeat, "__struct_id", JsonInt(1));
|
||||
jFeatList = JsonArrayInsert(jFeatList, jFeat);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1006, Adding racial feat: " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 999, Adding racial feat: " +
|
||||
Get2DAString("feat", "LABEL", nRaceFeat));
|
||||
nRaceRow++;
|
||||
}
|
||||
// Give class feats.
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1011, Checking for class feats.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1004, Checking for class feats.");
|
||||
int nClass = GetClassByPosition(1, oHenchman);
|
||||
string sGranted, sList;
|
||||
string sClsFeat2DAName = Get2DAString("classes", "FeatsTable", nClass);
|
||||
@@ -1026,7 +1026,7 @@ json ResetFeats(json jHenchman, object oHenchman)
|
||||
jFeat = GffAddWord(jFeat, "Feat", nClassFeat);
|
||||
jFeat = JsonObjectSet(jFeat, "__struct_id", JsonInt(1));
|
||||
jFeatList = JsonArrayInsert(jFeatList, jFeat);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1029, Adding class feat: " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1022, Adding class feat: " +
|
||||
Get2DAString("feat", "LABEL", nClassFeat));
|
||||
}
|
||||
}
|
||||
@@ -1036,7 +1036,7 @@ json ResetFeats(json jHenchman, object oHenchman)
|
||||
int nPackageFeat, nPackageRow;
|
||||
string sBonusFeat2DAName = Get2DAString("classes", "BonusFeatsTable", nClass);
|
||||
int nNumOfFeats = StringToInt(Get2DAString(sBonusFeat2DAName, "Bonus", nLevel));
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1039, Select " + IntToString(nNumOfFeats) + " bonus feats.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1032, Select " + IntToString(nNumOfFeats) + " bonus feats.");
|
||||
string sPackage2DAName = Get2DAString("packages", "FeatPref2DA", nClass);
|
||||
int nPackageMaxRow = Get2DARowCount(sPackage2DAName);
|
||||
// Give bonus feats based on the package.
|
||||
@@ -1059,7 +1059,7 @@ json ResetFeats(json jHenchman, object oHenchman)
|
||||
jFeat = GffAddWord(jFeat, "Feat", nClassFeat);
|
||||
jFeat = JsonObjectSet(jFeat, "__struct_id", JsonInt(1));
|
||||
jFeatList = JsonArrayInsert(jFeatList, jFeat);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1062, Adding class bonus feat: " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1055, Adding class bonus feat: " +
|
||||
Get2DAString("feat", "LABEL", nPackageFeat));
|
||||
nNumOfFeats--;
|
||||
}
|
||||
@@ -1073,27 +1073,27 @@ json ResetFeats(json jHenchman, object oHenchman)
|
||||
// Give picked feats from package.
|
||||
nNumOfFeats = 1;
|
||||
if(GetHasFeat(FEAT_QUICK_TO_MASTER, oHenchman)) nNumOfFeats++;
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1076, Select " + IntToString(nNumOfFeats) + " feats for character.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1069, Select " + IntToString(nNumOfFeats) + " feats for character.");
|
||||
nPackageRow = 0;
|
||||
while(nPackageRow < nPackageMaxRow || nNumOfFeats > 0)
|
||||
while(nPackageRow < nPackageMaxRow)
|
||||
{
|
||||
nClassRow = 0;
|
||||
nPackageFeat = StringToInt(Get2DAString(sPackage2DAName, "FeatIndex", nPackageRow));
|
||||
//WriteTimestampedLogEntry("pinc_henchmen, 1082, nPackageFeat: " + Get2DAString("feat", "LABEL", nPackageFeat) + ".");
|
||||
//WriteTimestampedLogEntry("pinc_henchmen, 1075, nPackageFeat: " + Get2DAString("feat", "LABEL", nPackageFeat) + ".");
|
||||
if(CanSelectFeat(jHenchman, oHenchman, nPackageFeat, jFeatList))
|
||||
{
|
||||
jFeat = JsonObject();
|
||||
jFeat = GffAddWord(jFeat, "Feat", nPackageFeat);
|
||||
jFeat = JsonObjectSet(jFeat, "__struct_id", JsonInt(1));
|
||||
jFeatList = JsonArrayInsert(jFeatList, jFeat);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1089, Selecting character feat: " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1082, Selecting character feat: " +
|
||||
Get2DAString("feat", "LABEL", nPackageFeat));
|
||||
nNumOfFeats--;
|
||||
}
|
||||
if(nNumOfFeats < 1) break;
|
||||
nPackageRow++;
|
||||
}
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1096, Adding feat list.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1089, Adding feat list.");
|
||||
jHenchman = GffReplaceList(jHenchman, "FeatList", jFeatList);
|
||||
return jHenchman;
|
||||
}
|
||||
@@ -1120,7 +1120,7 @@ json ResetSkills(json jHenchman, object oHenchman, int nLevel)
|
||||
jSkillList = JsonArrayInsert(jSkillList, jSkill);
|
||||
}
|
||||
// Give skill points based on the package.
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1122, Gets " + IntToString(nSkillPoints) + " skill points.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1116, Gets " + IntToString(nSkillPoints) + " skill points.");
|
||||
int nPackageSkill, nPackageRow, nCurrentRanks, bCrossClass, nClassRow, nNewRanks;
|
||||
string sPackage2DAName = Get2DAString("packages", "SkillPref2DA", nClass);
|
||||
int nPackageMaxRow = Get2DARowCount(sPackage2DAName);
|
||||
@@ -1149,7 +1149,7 @@ json ResetSkills(json jHenchman, object oHenchman, int nLevel)
|
||||
{
|
||||
jSkill = GffReplaceByte(jSkill, "Rank", nCurrentRanks + nNewRanks);
|
||||
jSkillList = JsonArraySet(jSkillList, nPackageSkill, jSkill);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1151, Adding " + IntToString(nNewRanks) +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1145, Adding " + IntToString(nNewRanks) +
|
||||
" ranks to " + Get2DAString("skills", "Label", nPackageSkill) +
|
||||
" CrossClass: " + IntToString(bCrossClass));
|
||||
nSkillPoints -= nNewRanks;
|
||||
@@ -1161,9 +1161,9 @@ json ResetSkills(json jHenchman, object oHenchman, int nLevel)
|
||||
}
|
||||
json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
{
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1163, Checking for spells known.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1157, Checking for spells known.");
|
||||
int nClass = GetClassByPosition(1, oHenchman);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1165, SpellCaster: " + Get2DAString("classes", "SpellCaster", nClass));
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1159, SpellCaster: " + Get2DAString("classes", "SpellCaster", nClass));
|
||||
if(Get2DAString("classes", "SpellCaster", nClass) == "0") return jClass;
|
||||
int nLevel = 0;
|
||||
// We remake the Known spell list if the character doesn't have a level list!
|
||||
@@ -1183,7 +1183,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
while(nSpellLevel < 10)
|
||||
{
|
||||
sSpellLevel = IntToString(nSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1185, Checking Spell Level: " + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1143, Checking Spell Level: " + sSpellLevel);
|
||||
// Recreate the 0th and 1st level based on the package.
|
||||
if(nSpellLevel < 2 && bSpellBookRestricted)
|
||||
{
|
||||
@@ -1205,7 +1205,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
{
|
||||
nSpellsKnown = StringToInt(Get2DAString(sSpellKnown2DAName, "SpellLevel" + sSpellLevel, nLevel));
|
||||
}
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1207, nSpellsKnown: " + IntToString(nSpellsKnown));
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1201, nSpellsKnown: " + IntToString(nSpellsKnown));
|
||||
jKnownList = JsonArray();
|
||||
nPackageRow = 0;
|
||||
while(nPackageRow < nPackageMaxRow && nSpellsKnown > 0)
|
||||
@@ -1227,7 +1227,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
if(JsonGetLength(jKnownList) == 0)
|
||||
{
|
||||
jClass = GffRemoveList(jClass, "KnownList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1229, Removing KnownList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1223, Removing KnownList" + sSpellLevel);
|
||||
}
|
||||
else if(JsonGetType(GffGetList(jClass, "KnownList" + sSpellLevel)) != JSON_TYPE_NULL)
|
||||
{
|
||||
@@ -1243,7 +1243,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
if(JsonGetType(jKnownList) != JSON_TYPE_NULL)
|
||||
{
|
||||
jClass = GffRemoveList(jClass, "KnownList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1245, Removing KnownList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1239, Removing KnownList" + sSpellLevel);
|
||||
}
|
||||
}
|
||||
if(bMemorizesSpells)
|
||||
@@ -1252,7 +1252,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
if(JsonGetType(jMemorizedList) != JSON_TYPE_NULL)
|
||||
{
|
||||
jClass = GffRemoveList(jClass, "MemorizedList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1254, Removing MemorizedList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1248, Removing MemorizedList" + sSpellLevel);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1263,7 +1263,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
jSpell = GffReplaceByte(jSpell, "NumSpellsLeft", nSpellsKnown);
|
||||
jSpellsPerDayList = JsonArraySet(jSpellsPerDayList, nSpellLevel, jSpell);
|
||||
jClass = GffReplaceList(jClass, "SpellsPerDayList", jSpellsPerDayList);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1265, Setting SpellsPerDay to " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1259, Setting SpellsPerDay to " +
|
||||
IntToString(nSpellsKnown));
|
||||
}
|
||||
nSpellLevel++;
|
||||
@@ -1289,8 +1289,8 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
}
|
||||
jHenchman = GffReplaceDword(jHenchman, "Experience", 0);
|
||||
jHenchman = GffReplaceFloat(jHenchman, "ChallengeRating", 1.0);
|
||||
int nPackage = GetLocalInt(oHenchman, "PACKAGE_SELECTED_1");
|
||||
if(nPackage) jHenchman = GffReplaceByte(jHenchman, "StartingPackage", nPackage);
|
||||
// int nPackage = GetLocalInt(oHenchman, "PACKAGE_SELECTED_1");
|
||||
// if(nPackage) jHenchman = GffReplaceByte(jHenchman, "StartingPackage", nPackage);
|
||||
string s2DA = Get2DAString("classes", "AttackBonusTable", nClass);
|
||||
int nAtk = StringToInt(Get2DAString(s2DA, "BAB", 0));
|
||||
jHenchman = GffReplaceByte(jHenchman, "BaseAttackBonus", nAtk);
|
||||
@@ -1304,7 +1304,7 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
json jLvlStatList = GffGetList(jHenchman, "LvlStatList");
|
||||
if(JsonGetType(jLvlStatList) != JSON_TYPE_NULL)
|
||||
{
|
||||
//WriteTimestampedLogEntry("pinc_henchmen 1289, jLvlStatList: " + JsonDump(jLvlStatList, 4));
|
||||
//WriteTimestampedLogEntry("pinc_henchmen 1300, jLvlStatList: " + JsonDump(jLvlStatList, 4));
|
||||
int nLevel = 1, nLevelTrack = 1;
|
||||
int nAbilityStatIncrease, nAbility;
|
||||
string sAbility;
|
||||
@@ -1312,7 +1312,7 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
json jLevel = JsonArrayGet(jLvlStatList, nLevel);
|
||||
while(JsonGetType(jLevel) != JSON_TYPE_NULL)
|
||||
{
|
||||
WriteTimestampedLogEntry("inc_henchmen, 1314, Checking level " + IntToString(nLevelTrack));
|
||||
WriteTimestampedLogEntry("inc_henchmen, 1308, Checking level " + IntToString(nLevelTrack));
|
||||
// Remove all Ability score increases for each level from ability scores.
|
||||
jAbility = GffGetByte(jLevel, "LvlStatAbility");
|
||||
if(JsonGetType(jAbility) != JSON_TYPE_NULL)
|
||||
@@ -1326,7 +1326,7 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
if(nAbilityStatIncrease == ABILITY_CHARISMA) sAbility = "Cha";
|
||||
nAbility = JsonGetInt(GffGetByte(jHenchman, sAbility)) - 1;
|
||||
jHenchman = GffReplaceByte(jHenchman, sAbility, nAbility);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1328, Removing " + sAbility + " level bonus ability score point.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1314, Removing " + sAbility + " level bonus ability score point.");
|
||||
}
|
||||
jLvlStatList = JsonArrayDel(jLvlStatList, nLevel);
|
||||
// Note: nLevel is not incremented since we are removing the previous level.
|
||||
@@ -1352,7 +1352,7 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
jClass = ResetSpellsKnown(jClass, oHenchman);
|
||||
jClassList = JsonArraySet(jClassList, 0, jClass);
|
||||
jHenchman = GffReplaceList(jHenchman, "ClassList", jClassList);
|
||||
//WriteTimestampedLogEntry("pinc_henchmen 1331, jHenchman: " + JsonDump(jHenchman, 4));
|
||||
//WriteTimestampedLogEntry("pinc_henchmen 1348, jHenchman: " + JsonDump(jHenchman, 4));
|
||||
location lLocation = GetLocation(oHenchman);
|
||||
int nFamiliar, nCompanion;
|
||||
object oCompanion = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oHenchman);
|
||||
@@ -1571,4 +1571,3 @@ void CreateCharacterDescriptionNUI(object oPC, string sName, string sIcon, strin
|
||||
// Row 2
|
||||
NuiSetBind(oPC, nToken, "btn_ok_event", JsonBool(TRUE));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user