2025/12/15 Update
Updated PEPS. Updated nim tools.
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);
|
||||
}
|
||||
|
||||
@@ -10,9 +10,6 @@ void main()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
int nSpell = StringToInt (GetScriptParam ("nSpell"));
|
||||
// Save the original form so we can check when we turn back (Add 1 so we don't save a 0!).
|
||||
SetLocalInt (oHenchman, AI_NORMAL_FORM, GetAppearanceType (oHenchman) + 1);
|
||||
SetLocalString (oHenchman, AI_COMBAT_SCRIPT, "ai_a_polymorphed");
|
||||
ActionCastSpellAtObject (nSpell, oHenchman, 255, TRUE);
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -68,7 +68,7 @@ int StartingConditional()
|
||||
{
|
||||
string sHealingIn = IntToString(GetLocalInt(oAssociate, AI_HEAL_IN_COMBAT_LIMIT)) + "%";
|
||||
string sHealingOut = IntToString(GetLocalInt(oAssociate, AI_HEAL_OUT_OF_COMBAT_LIMIT)) + "%";
|
||||
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 5, "I'm healing our allies if they go below " +
|
||||
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 4, "I'm healing our allies if they go below " +
|
||||
sHealingIn + " health in combat and " + sHealingOut + " out of combat.");
|
||||
}
|
||||
else if(sParam == "Spells")
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,8 +10,7 @@ void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
// Added code to allow for permanent associates in the battle!
|
||||
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "13", GetName(oCreature) + " has died!" +
|
||||
" AI_RULE_PERM_ASSOC: " + IntToString(GetLocalInt(GetModule(), AI_RULE_PERM_ASSOC)));
|
||||
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "13", GetName(oCreature) + " has died!");
|
||||
object oModule = GetModule();
|
||||
if(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))
|
||||
{
|
||||
@@ -22,6 +21,7 @@ void main()
|
||||
oAssociate = GetAssociate(nIndex, oCreature);
|
||||
if(oAssociate != OBJECT_INVALID)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "24", GetName(oAssociate) + " being set to permanent!");
|
||||
SetIsDestroyable(FALSE, FALSE, FALSE, oAssociate);
|
||||
DelayCommand(0.1, ChangeToStandardFaction(oAssociate, STANDARD_FACTION_HOSTILE));
|
||||
DelayCommand(3.0, SetIsDestroyable(TRUE, FALSE, FALSE, oAssociate));
|
||||
@@ -31,12 +31,15 @@ void main()
|
||||
// Remove the widget!
|
||||
object oPC = GetMaster(oCreature);
|
||||
if(oPC != OBJECT_INVALID)
|
||||
{
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "35", GetName(oPC) + " Removing associates widget!");
|
||||
NuiDestroy(oPC, NuiFindWindow(oPC, ai_GetAssociateType(oPC, oCreature) + AI_WIDGET_NUI));
|
||||
DelayCommand(0.5, ai_CheckXPPartyScale(oCreature));
|
||||
DelayCommand(2.0, ai_ClearCreatureActions(TRUE));
|
||||
}
|
||||
DelayCommand(2.0, ai_ClearCombatState(oCreature));
|
||||
ExecuteScript(GetLocalString(oCreature, "AI_ON_DEATH"));
|
||||
ChangeToStandardFaction(oCreature, STANDARD_FACTION_DEFENDER);
|
||||
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "42", "Execute second OnDeath script: " + GetLocalString(oCreature, "AI_ON_DEATH"));
|
||||
ExecuteScript(GetLocalString(oCreature, "AI_ON_DEATH"), oCreature);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "nw_inc_gff"
|
||||
#include "x0_i0_assoc"
|
||||
#include "0i_menus"
|
||||
#include "0i_module"
|
||||
#include "0i_player_target"
|
||||
// Save a window ID to the database.
|
||||
void ai_SaveWindowLocation(object oPC, int nToken, string sAssociateType, string sWindowID);
|
||||
@@ -32,10 +33,6 @@ void ai_RulePercDistInc(object oPC, object oModule, int nIncrement, int nToken);
|
||||
// Adds a spell to a json AI restricted spell list then returns jRules.
|
||||
// bRestrict = TRUE will add to the list FALSE will remove it from the list.
|
||||
json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE);
|
||||
// Turns on oAssociate AI, Setting all event scripts.
|
||||
void ai_TurnOn(object oPC, object oAssociate, string sAssociateType);
|
||||
// Turns off oAssociate AI, Setting all event scripts.
|
||||
void ai_TurnOff(object oPC, object oAssociate, string sAssociateType);
|
||||
// Adds a henchman back into the players party.
|
||||
object ai_AddHenchman(object oPC, json jHenchman, location lLocation, int nFamiliar, int nCompanion);
|
||||
|
||||
@@ -94,10 +91,20 @@ void main()
|
||||
json jData = NuiGetUserData(oPC, nToken);
|
||||
object oAssociate = StringToObject(JsonGetString(JsonArrayGet(jData, 0)));
|
||||
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
|
||||
if(ai_GetIsDungeonMaster(oPC))
|
||||
{
|
||||
if(!NuiFindWindow(oPC, "dm" + AI_WIDGET_NUI))
|
||||
{
|
||||
ai_SendMessages(GetName(oPC) + " is now a Dungeon Master! Loading Dungeon Master widget.", AI_COLOR_YELLOW, oPC);
|
||||
ai_CheckDMStart(oPC);
|
||||
}
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nToken));
|
||||
return;
|
||||
}
|
||||
if(!ai_GetIsCharacter(oAssociate) && !GetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE") &&
|
||||
(oAssociate == OBJECT_INVALID || GetMaster(oAssociate) != oPC))
|
||||
{
|
||||
ai_SendMessages("This creature is no longer in your party!", AI_COLOR_RED, oPC);
|
||||
ai_SendMessages(GetName(oAssociate) + " is no longer in your party!", AI_COLOR_RED, oPC);
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nToken));
|
||||
return;
|
||||
}
|
||||
@@ -196,57 +203,6 @@ void main()
|
||||
aiSaveAssociateModesToDb(oPC, oPC);
|
||||
}
|
||||
}
|
||||
else if(sElem == "btn_toggle_assoc_widget")
|
||||
{
|
||||
int bWidgetOff = !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc");
|
||||
string sAssocType;
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc", bWidgetOff);
|
||||
object oAssoc = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
oAssoc = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
oAssoc = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
oAssoc = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
int nIndex;
|
||||
object oHenchman;
|
||||
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
|
||||
{
|
||||
oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
|
||||
if(oHenchman != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oHenchman);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oHenchman, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oHenchman);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sElem == "btn_effect_icon")
|
||||
{
|
||||
if(ai_GetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT))
|
||||
@@ -280,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);
|
||||
@@ -318,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));
|
||||
}
|
||||
@@ -354,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")
|
||||
{
|
||||
@@ -579,6 +541,60 @@ void main()
|
||||
else if(sElem == "btn_familiar_name") ai_SetCompanionName(oPC, oAssociate, nToken, ASSOCIATE_TYPE_FAMILIAR);
|
||||
else if(sElem == "btn_companion_name") ai_SetCompanionName(oPC, oAssociate, nToken, ASSOCIATE_TYPE_ANIMALCOMPANION);
|
||||
else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oPC, sElem);
|
||||
else if(sElem == "btn_toggle_assoc_widget")
|
||||
{
|
||||
int bWidgetOff = !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc");
|
||||
string sAssocType, sText;
|
||||
if(bWidgetOff) sText = " Associate Widgets [Off]";
|
||||
else sText = " Associate Widgets [On]";
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_toggle_assoc_widget_tooltip", sText);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc", bWidgetOff);
|
||||
object oAssoc = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
oAssoc = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
oAssoc = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
oAssoc = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
int nIndex;
|
||||
object oHenchman;
|
||||
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
|
||||
{
|
||||
oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
|
||||
if(oHenchman != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oHenchman);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oHenchman, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oHenchman);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sEvent == "watch")
|
||||
{
|
||||
@@ -597,10 +613,14 @@ void main()
|
||||
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck));
|
||||
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
|
||||
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
}
|
||||
}
|
||||
else if(sElem == "chbx_buff_rest_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_BUFF_REST, oAssociate, sAssociateType, nToken, sElem);
|
||||
else if(sElem == "chbx_toggle_assoc_widget_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_ASSOC_WIDGETS_OFF, oAssociate, sAssociateType, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_action_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_ACTION, oAssociate, sAssociateType, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_guard_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_GUARD, oAssociate, sAssociateType, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_hold_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_HOLD, oAssociate, sAssociateType, nToken, sElem);
|
||||
@@ -623,8 +643,11 @@ void main()
|
||||
else if(sElem == "chbx_companion_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_COMPANION, oAssociate, sAssociateType, nToken, sElem);
|
||||
else if(sElem == "cmb_familiar_selected") ai_SetCompanionType(oPC, oAssociate, nToken, ASSOCIATE_TYPE_FAMILIAR);
|
||||
else if(sElem == "cmb_companion_selected") ai_SetCompanionType(oPC, oAssociate, nToken, ASSOCIATE_TYPE_ANIMALCOMPANION);
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
}
|
||||
}
|
||||
else if(sEvent == "mousescroll")
|
||||
{
|
||||
@@ -635,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
|
||||
{
|
||||
@@ -642,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;
|
||||
@@ -722,8 +751,11 @@ void main()
|
||||
else if(sElem == "chbx_ignore_traps_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_IGNORE_TRAPS, oAssociate, sAssociateType, nToken, sElem);
|
||||
else if(sElem == "chbx_perc_range_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_PERC_RANGE, oAssociate, sAssociateType, nToken, sElem);
|
||||
else if(sElem == "cmb_ai_script_selected") ai_SetAIScript(oPC, oAssociate, nToken);
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
}
|
||||
}
|
||||
else if(sEvent == "mousescroll")
|
||||
{
|
||||
@@ -863,6 +895,60 @@ void main()
|
||||
else if(sElem == "btn_update_widget") ai_UpdateAssociateWidget(oPC, oAssociate);
|
||||
else if(GetStringLeft(sElem, 15) == "btn_exe_plugin_") ai_Plugin_Execute(oPC, sElem);
|
||||
else if(GetStringLeft(sElem, 11) == "btn_widget_") ai_SelectWidgetSpellTarget(oPC, oAssociate, sElem);
|
||||
else if(sElem == "btn_toggle_assoc_widget")
|
||||
{
|
||||
int bWidgetOff = !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc");
|
||||
string sAssocType, sText;
|
||||
if(bWidgetOff) sText = "Associate Widgets [Off]";
|
||||
else sText = "Associate Widgets [On]";
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_toggle_assoc_widget_tooltip", sText);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc", bWidgetOff);
|
||||
object oAssoc = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
oAssoc = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
oAssoc = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
oAssoc = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
|
||||
if(oAssoc != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oAssoc);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oAssoc);
|
||||
}
|
||||
int nIndex;
|
||||
object oHenchman;
|
||||
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
|
||||
{
|
||||
oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
|
||||
if(oHenchman != OBJECT_INVALID)
|
||||
{
|
||||
sAssocType = ai_GetAssociateType(oPC, oHenchman);
|
||||
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oHenchman, sAssocType, bWidgetOff);
|
||||
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
|
||||
else ai_CreateWidgetNUI(oPC, oHenchman);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(sEvent == "mousescroll")
|
||||
{
|
||||
@@ -881,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
|
||||
{
|
||||
@@ -897,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")
|
||||
@@ -1174,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");
|
||||
@@ -1209,8 +1302,11 @@ void main()
|
||||
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nToken));
|
||||
DelayCommand(0.1, ai_CreatePluginNUI(oPC));
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
}
|
||||
}
|
||||
if(sElem == "btn_clear_plugins")
|
||||
{
|
||||
@@ -1229,8 +1325,11 @@ void main()
|
||||
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nToken));
|
||||
DelayCommand(0.1, ai_CreatePluginNUI(oPC));
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
}
|
||||
}
|
||||
else if(sElem == "btn_add_plugin")
|
||||
{
|
||||
@@ -1249,8 +1348,11 @@ void main()
|
||||
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nToken));
|
||||
DelayCommand(0.1, ai_CreatePluginNUI(oPC));
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
}
|
||||
}
|
||||
else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oPC, sElem);
|
||||
}
|
||||
@@ -1265,8 +1367,11 @@ void main()
|
||||
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck));
|
||||
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
|
||||
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -1348,11 +1453,14 @@ void main()
|
||||
}
|
||||
else if(sEvent == "close")
|
||||
{
|
||||
int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
|
||||
if(nUIToken)
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
|
||||
if(nUIToken)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -1435,11 +1543,14 @@ void main()
|
||||
}
|
||||
else if(sEvent == "close")
|
||||
{
|
||||
int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
|
||||
if(nUIToken)
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
|
||||
if(nUIToken)
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -1615,6 +1726,7 @@ void main()
|
||||
if(GetLocalInt(oAssociate, "AI_KNOWN_SPELL_CHANGE"))
|
||||
{
|
||||
RemoveHenchman(oPC, oAssociate);
|
||||
ChangeToStandardFaction(oAssociate, STANDARD_FACTION_DEFENDER);
|
||||
json jHenchman = ObjectToJson(oAssociate, TRUE);
|
||||
json jClassList = GetLocalJson(oAssociate, AI_CLASS_LIST_JSON);
|
||||
jHenchman = GffReplaceList(jHenchman, "ClassList", jClassList);
|
||||
@@ -1627,8 +1739,12 @@ void main()
|
||||
AssignCommand(oAssociate, SetIsDestroyable(TRUE, FALSE, FALSE));
|
||||
DestroyObject(oAssociate);
|
||||
oAssociate = ai_AddHenchman(oPC, jHenchman, lLocation, nFamiliar, nCompanion);
|
||||
DeleteLocalJson(oAssociate, AI_CLASS_LIST_JSON);
|
||||
DeleteLocalInt(oAssociate, "AI_KNOWN_SPELL_CHANGE");
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -1698,7 +1814,11 @@ void ai_AddAssociate(object oPC, int nToken, json jAssociate, location lLocation
|
||||
AddHenchman(oPC, oAssociate);
|
||||
DeleteLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE");
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nToken));
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
|
||||
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
|
||||
{
|
||||
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
|
||||
}
|
||||
if(nRange) SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION, nRange);
|
||||
if(nFamiliar) SummonFamiliar(oAssociate);
|
||||
if(nCompanion) SummonAnimalCompanion(oAssociate);
|
||||
@@ -1816,12 +1936,12 @@ void ai_Perc_Range(object oPC, object oAssociate, int nToken, string sAssociateT
|
||||
SetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE", TRUE);
|
||||
int nBtnPercRange = GetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION + "_MENU");
|
||||
string sText, sText2;
|
||||
float fRange = 20.0;
|
||||
float fRange = 25.0;
|
||||
if(nBtnPercRange == 8)
|
||||
{
|
||||
sText = "short";
|
||||
sText2 = " Perception Range Short [10 meters Sight / 10 meters Listen]";
|
||||
fRange = 10.0;
|
||||
fRange = 15.0;
|
||||
}
|
||||
else if(nBtnPercRange == 9)
|
||||
{
|
||||
@@ -1832,7 +1952,7 @@ void ai_Perc_Range(object oPC, object oAssociate, int nToken, string sAssociateT
|
||||
{
|
||||
sText = "long";
|
||||
sText2 = " Perception Range Long [35 meters Sight / 20 meters Listen]";
|
||||
fRange = 35.0;
|
||||
fRange = 40.0;
|
||||
}
|
||||
else if(nBtnPercRange == 11)
|
||||
{
|
||||
@@ -1914,49 +2034,6 @@ json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE)
|
||||
SetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS, jRSpells);
|
||||
return JsonObjectSet(jRules, AI_RULE_RESTRICTED_SPELLS, jRSpells);
|
||||
}
|
||||
void ai_TurnOn(object oPC, object oTarget, string sAssociateType)
|
||||
{
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ai_tooltip", " AI On");
|
||||
ai_SendMessages("AI turned on for " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC);
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "xx_pc_1_hb");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_NOTICE, "xx_pc_2_percept");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "xx_pc_3_endround");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "xx_pc_4_convers");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "xx_pc_5_phyatked");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "xx_pc_6_damaged");
|
||||
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DEATH, "");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "xx_pc_8_disturb");
|
||||
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
|
||||
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_RESTED, "");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "xx_pc_b_castat");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "xx_pc_e_blocked");
|
||||
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "");
|
||||
// This sets the script for the PC to run AI based on class.
|
||||
ai_SetAssociateAIScript(oTarget, FALSE);
|
||||
// Set so PC can hear associates talking in combat.
|
||||
ai_SetListeningPatterns(oTarget);
|
||||
}
|
||||
void ai_TurnOff(object oPC, object oAssociate, string sAssociateType)
|
||||
{
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ai_tooltip", " AI Off");
|
||||
ai_SendMessages("AI Turned off for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC);
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_NOTICE, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "");
|
||||
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DEATH, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "");
|
||||
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
|
||||
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_RESTED, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "");
|
||||
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "");
|
||||
DeleteLocalInt(oAssociate, "AI_I_AM_BEING_HEALED");
|
||||
DeleteLocalString(oAssociate, "AIScript");
|
||||
ai_ClearCreatureActions();
|
||||
}
|
||||
object ai_AddHenchman(object oPC, json jHenchman, location lLocation, int nFamiliar, int nCompanion)
|
||||
{
|
||||
jHenchman = GffReplaceResRef(jHenchman, "ScriptSpawn", "");
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
Menu event script
|
||||
sEvent: close, click, mousedown, mouseup, watch (if bindwatch is set).
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_menus"
|
||||
#include "0i_menus_dm"
|
||||
void ai_SetDMWidgetButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
|
||||
void ai_SetDMWAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
|
||||
@@ -32,6 +33,16 @@ void main()
|
||||
// " nToken: " + IntToString(nToken) + " oPC: " + GetName(oPC));
|
||||
//WriteTimestampedLogEntry("0e_nui, 58, sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem +
|
||||
// " nToken: " + IntToString(nToken) + " oDM: " + GetName(oDM));
|
||||
if(ai_GetIsCharacter(oDM))
|
||||
{
|
||||
if(!NuiFindWindow(oDM, "pc" + AI_WIDGET_NUI))
|
||||
{
|
||||
ai_SendMessages(GetName(oDM) + " is now a Player! Loading player widget.", AI_COLOR_YELLOW, oDM);
|
||||
ai_CreateWidgetNUI(oDM, oDM);
|
||||
}
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
return;
|
||||
}
|
||||
//**************************************************************************
|
||||
string sName = ai_RemoveIllegalCharacters(GetName(oDM));
|
||||
// Watch to see if the window moves and save.
|
||||
@@ -197,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");
|
||||
@@ -232,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));
|
||||
@@ -253,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);
|
||||
|
||||
@@ -15,9 +15,5 @@ void main()
|
||||
object oCreature = OBJECT_SELF;
|
||||
// This can be moved to the OnClientLoad script event of your module.
|
||||
if(ai_GetIsCharacter(oCreature)) ai_CheckPCStart(oCreature);
|
||||
// If this is a server you can add this as well.
|
||||
else if(AI_SERVER && (GetIsDM(oCreature) || GetIsPlayerDM(oCreature)))
|
||||
{
|
||||
ai_CheckPCStart(oCreature);
|
||||
}
|
||||
else if(ai_GetIsDungeonMaster(oCreature)) ai_CheckDMStart(oCreature);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
action of the target.
|
||||
AI_TARGET_MODE is the constant used.
|
||||
AI_TARGET_ASSOCIATE is the associate that triggered the target mode.
|
||||
|
||||
AI_TARGET_MODE_ON defines if the player is in target mode for a henchman instead of the PC.
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_player_target"
|
||||
void main()
|
||||
@@ -31,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())
|
||||
@@ -38,50 +41,61 @@ 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")
|
||||
{
|
||||
ai_SendMessages("You have exited selecting an action for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC);
|
||||
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
|
||||
// Clean up any PC AI being turned on as well as variables.
|
||||
DeleteLocalObject(oPC, AI_TARGET_ASSOCIATE);
|
||||
DeleteLocalInt(oPC, AI_TARGET_MODE_ON);
|
||||
DeleteLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE);
|
||||
// Make sure the camera goes back to the player since we are leaving henchmen control.
|
||||
if(GetLocalObject(oPC, "AI_CAMERA_ON_ASSOCIATE") != OBJECT_INVALID)
|
||||
{
|
||||
if(GetLocalInt(oPC, sGhostModeVarname))
|
||||
{
|
||||
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
|
||||
DeleteLocalInt(oAssociate, sGhostModeVarname);
|
||||
}
|
||||
DeleteLocalObject(oPC, "AI_CAMERA_ON_ASSOCIATE");
|
||||
AttachCamera(oPC, oPC);
|
||||
if(!GetLocalInt(GetModule(), AI_USING_PRC)) ai_TurnOff(oPC, oPC, "pc");
|
||||
}
|
||||
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_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.
|
||||
else if(sTargetMode == "ASSOCIATE_USE_ITEM" ||
|
||||
sTargetMode == "ASSOCIATE_USE_FEAT" ||
|
||||
sTargetMode == "ASSOCIATE_CAST_SPELL" ||
|
||||
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
|
||||
@@ -89,45 +103,60 @@ 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")
|
||||
{
|
||||
if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID;
|
||||
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")
|
||||
{
|
||||
if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID;
|
||||
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")
|
||||
{
|
||||
@@ -137,18 +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.
|
||||
string sModuleTargetScript = GetLocalString(GetModule(), AI_MODULE_TARGET_EVENT);
|
||||
ExecuteScript(sModuleTargetScript);
|
||||
}
|
||||
// Get saved module player target script and execute it for pass through compatibility.
|
||||
ExecuteScript(GetLocalString(GetModule(), AI_MODULE_TARGET_EVENT));
|
||||
}
|
||||
}
|
||||
|
||||
317
_module/nss/0e_prc_id_events.nss
Normal file
317
_module/nss/0e_prc_id_events.nss
Normal file
@@ -0,0 +1,317 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
// Script Name: 0e_prc_id_events
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Infinite Dungeons monster event handler while using the PRC.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_actions"
|
||||
#include "x0_i0_assoc"
|
||||
// Followers special heartbeat script.
|
||||
void ai_hen_id1_heart(object oCreature);
|
||||
// Followers special conversation script.
|
||||
void ai_hen_id1_convo(object oCreature, int nMatch);
|
||||
// Followers special perception script.
|
||||
void ai_hen_id1_percept(object oCreature);
|
||||
// Followers special end of round script.
|
||||
void ai_hen_id1_endcombat(object oCreature, int bFollower);
|
||||
// Followers special castat script.
|
||||
void ai_hen_id1_castat(object oCreature);
|
||||
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
int nEvent = GetCurrentlyRunningEvent();
|
||||
int bFollower = GetLocalInt(oCreature, "bFollower");
|
||||
switch (nEvent)
|
||||
{
|
||||
case EVENT_SCRIPT_CREATURE_ON_HEARTBEAT:
|
||||
{
|
||||
if(bFollower)
|
||||
{
|
||||
if(GetImmortal(oCreature)) SetImmortal(oCreature, FALSE);
|
||||
ai_hen_id1_heart(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecuteScript("nw_c2_default1", oCreature);
|
||||
ExecuteScript("prc_npc_hb", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_NOTICE:
|
||||
{
|
||||
if(bFollower) ai_hen_id1_percept(oCreature);
|
||||
else
|
||||
{
|
||||
ExecuteScript("nw_c2_default2", oCreature);
|
||||
ExecuteScript("prc_npc_percep", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_DIALOGUE:
|
||||
{
|
||||
int nMatch = GetListenPatternNumber();
|
||||
if(nMatch == -1)
|
||||
{
|
||||
if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature) ||
|
||||
GetLocalInt(oCreature, AI_AM_I_SEARCHING)) return;
|
||||
ai_ClearCreatureActions();
|
||||
string sConversation = GetLocalString(oCreature, "sConversation");
|
||||
if(sConversation != "") BeginConversation(sConversation);
|
||||
else BeginConversation();
|
||||
}
|
||||
if(bFollower) ai_hen_id1_convo(oCreature, nMatch);
|
||||
else
|
||||
{
|
||||
//ExecuteScript("nw_c2_default4", oCreature);
|
||||
ExecuteScript("prc_npc_conv", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED:
|
||||
{
|
||||
if(bFollower) ExecuteScript("nw_ch_ac5", oCreature);
|
||||
else
|
||||
{
|
||||
ExecuteScript("nw_c2_default5", oCreature);
|
||||
ExecuteScript("prc_npc_physatt", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_DAMAGED:
|
||||
{
|
||||
if(bFollower) ExecuteScript("nw_ch_ac6", oCreature);
|
||||
else
|
||||
{
|
||||
ExecuteScript("nw_c2_default6", oCreature);
|
||||
ExecuteScript("prc_npc_damaged", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT:
|
||||
{
|
||||
if(bFollower) ai_hen_id1_castat(oCreature);
|
||||
else
|
||||
{
|
||||
ExecuteScript("nw_c2_defaultb", oCreature);
|
||||
ExecuteScript("prc_npc_spellat", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND:
|
||||
{
|
||||
if(bFollower) ai_hen_id1_endcombat(oCreature, bFollower);
|
||||
else
|
||||
{
|
||||
ExecuteScript("nw_c2_default3", oCreature);
|
||||
ExecuteScript("prc_npc_combat", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR:
|
||||
{
|
||||
if(bFollower) ExecuteScript("nw_ch_ace", oCreature);
|
||||
else
|
||||
{
|
||||
ExecuteScript("nw_c2_defaulte", oCreature);
|
||||
ExecuteScript("prc_npc_blocked", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_RESTED:
|
||||
{
|
||||
if(bFollower) ExecuteScript("nw_ch_aca", oCreature);
|
||||
else ExecuteScript("prc_npc_rested", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_DISTURBED:
|
||||
{
|
||||
if(bFollower) ExecuteScript("nw_ch_ac8", oCreature);
|
||||
else
|
||||
{
|
||||
ExecuteScript("nw_c2_default8", oCreature);
|
||||
ExecuteScript("prc_npc_disturb", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_DEATH:
|
||||
{
|
||||
if(bFollower) ExecuteScript("nw_ch_ac7", oCreature);
|
||||
else
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", oCreature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ai_hen_id1_heart(object oCreature)
|
||||
{
|
||||
// Sometimes they slip out of this mode!
|
||||
if(GetAssociateState(NW_ASC_MODE_DYING, oCreature) &&
|
||||
GetCommandable())
|
||||
{
|
||||
ActionPlayAnimation(ANIMATION_LOOPING_DEAD_FRONT, 1.0, 65.0);
|
||||
SetCommandable(FALSE);
|
||||
}
|
||||
ExecuteScript("nw_ch_ac1", oCreature);
|
||||
}
|
||||
void ai_hen_id1_convo(object oCreature, int nMatch)
|
||||
{
|
||||
if(nMatch == ASSOCIATE_COMMAND_INVENTORY)
|
||||
{
|
||||
// * cannot modify disabled equipment
|
||||
if(!GetLocalInt(OBJECT_SELF, "X2_JUST_A_DISABLEEQUIP"))
|
||||
{
|
||||
OpenInventory(oCreature, GetLastSpeaker());
|
||||
}
|
||||
// * feedback as to why
|
||||
else SendMessageToPCByStrRef(GetMaster(), 100895);
|
||||
return;
|
||||
}
|
||||
else if(nMatch == ASSOCIATE_COMMAND_LEAVEPARTY)
|
||||
{
|
||||
object oMaster = GetMaster();
|
||||
string sTag = GetTag(GetArea(oMaster));
|
||||
// * henchman cannot be kicked out in the reaper realm
|
||||
// * Followers can never be kicked out
|
||||
if (sTag == "GatesofCania" || GetIsFollower(oCreature)) return;
|
||||
if(GetIsObjectValid(oMaster))
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
if(GetAssociateType(oCreature) == ASSOCIATE_TYPE_HENCHMAN)
|
||||
{
|
||||
string sConversation = GetLocalString(oCreature, "sConversation");
|
||||
if (sConversation == "id1_plotgiver")
|
||||
{
|
||||
string sVariable = GetLocalString(oCreature, "sVariable");
|
||||
object oDungeon = GetLocalObject(GetModule(), "oCurrentDungeon");
|
||||
SetLocalInt(oDungeon, "b" + sVariable + "Gone", FALSE);
|
||||
}
|
||||
RemoveHenchman(oMaster);
|
||||
DestroyObject(oCreature);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
ExecuteScript("nw_ch_ac4", oCreature);
|
||||
}
|
||||
void ai_hen_id1_percept(object oCreature)
|
||||
{
|
||||
// If henchman is dying and Player disappears then force a respawn of the henchman
|
||||
if (GetIsHenchmanDying(oCreature))
|
||||
{
|
||||
// The henchman must be removed otherwise their corpse will follow the player
|
||||
object oOldMaster = GetMaster();
|
||||
object oPC = GetLastPerceived();
|
||||
int bVanish = GetLastPerceptionVanished();
|
||||
if(GetIsObjectValid(oPC) && bVanish)
|
||||
{
|
||||
if (oPC == oOldMaster)
|
||||
{
|
||||
RemoveHenchman(oPC, oCreature);
|
||||
// Only in chapter 1
|
||||
if(GetTag(GetModule()) == "x0_module1")
|
||||
{
|
||||
SetCommandable(TRUE);
|
||||
DoRespawn(oPC, oCreature); // Should teleport henchman back
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ExecuteScript("nw_ch_ac2", oCreature);
|
||||
}
|
||||
void ai_hen_id1_endcombat(object oCreature, int bFollower)
|
||||
{
|
||||
if (ai_GetIsInCombat(oCreature))
|
||||
{
|
||||
int nNum;
|
||||
int nLine;
|
||||
string sString;
|
||||
int nCreature;
|
||||
int bIntelligent;
|
||||
int nRandom = d100();
|
||||
// chance of a oneliner
|
||||
int nOnelinerPercentage = GetLocalInt(GetModule(), "nFlagCombatOneLinerFrequencyValue");
|
||||
if(nRandom <= nOnelinerPercentage)
|
||||
{
|
||||
string sCreature = GetLocalString(oCreature, "sVariable");
|
||||
// if the current creature is hostile towards PCs
|
||||
if(sCreature != "")
|
||||
{
|
||||
object oDungeon = GetLocalObject(GetModule(), "oCurrentDungeon");
|
||||
if(GetIsReactionTypeHostile(GetFirstPC()))
|
||||
{
|
||||
nCreature = GetLocalInt(oDungeon, "n" + sCreature);
|
||||
bIntelligent = GetLocalInt(oDungeon, "bListCreature" + IntToString(nCreature) + "Intelligent");
|
||||
if(bIntelligent)
|
||||
{
|
||||
nNum = GetLocalInt(GetModule(), "nLinesHostileNum");
|
||||
nLine = Random(nNum) + 1;
|
||||
if(nLine > 0)
|
||||
{
|
||||
sString = GetLocalString(GetModule(), "sLinesHostile" + IntToString(nLine));
|
||||
SpeakString(sString, TALKVOLUME_SHOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nCreature = GetLocalInt(oDungeon, "n" + sCreature);
|
||||
bIntelligent = GetLocalInt(oDungeon, "bListCreature" + IntToString(nCreature) + "Intelligent");
|
||||
if(bIntelligent)
|
||||
{
|
||||
nNum = GetLocalInt(GetModule(), "nLinesAlliesNum");
|
||||
nLine = Random(nNum) + 1;
|
||||
if (nLine > 0)
|
||||
{
|
||||
sString = GetLocalString(GetModule(), "sLinesAllies" + IntToString(nLine));
|
||||
SpeakString(sString, TALKVOLUME_SHOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bFollower) ExecuteScript("nw_ch_ac3", oCreature);
|
||||
else ExecuteScript("nw_c2_default3", oCreature);
|
||||
}
|
||||
void ai_hen_id1_castat(object oCreature)
|
||||
{
|
||||
if(!GetLastSpellHarmful())
|
||||
{
|
||||
int nSpell = GetLastSpell();
|
||||
if(nSpell == SPELL_RAISE_DEAD || nSpell == SPELL_RESURRECTION)
|
||||
{
|
||||
object oCaster = GetLastSpellCaster();
|
||||
// Restore merchant faction to neutral
|
||||
SetStandardFactionReputation(STANDARD_FACTION_MERCHANT, 100, oCaster);
|
||||
SetStandardFactionReputation(STANDARD_FACTION_COMMONER, 100, oCaster);
|
||||
SetStandardFactionReputation(STANDARD_FACTION_DEFENDER, 100, oCaster);
|
||||
ClearPersonalReputation(oCaster, oCreature);
|
||||
AssignCommand(oCreature, SurrenderToEnemies());
|
||||
AssignCommand(oCreature, ai_ClearCreatureActions(TRUE));
|
||||
// Reset henchmen attack state - Oct 28 (BK)
|
||||
ai_SetAIMode(oCreature, AI_MODE_DEFEND_MASTER, FALSE);
|
||||
ai_SetAIMode(oCreature, AI_MODE_STAND_GROUND, FALSE);
|
||||
ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE);
|
||||
ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE);
|
||||
ai_SetAIMode(oCreature, AI_MODE_COMMANDED, FALSE);
|
||||
// Oct 30 - If player previously hired this hench
|
||||
// then just have them rejoin automatically
|
||||
if(GetPlayerHasHired(oCaster, oCreature))
|
||||
{
|
||||
// Feb 11, 2004 - Jon: Don't fire the HireHenchman function if the
|
||||
// henchman is already oCaster's associate. Fixes a silly little problem
|
||||
// that occured when you try to raise a henchman who wasn't actually dead.
|
||||
if(GetMaster(oCreature)!= oCaster) HireHenchman(oCaster, oCreature, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
string sFile = GetDialogFileToUse(oCaster);
|
||||
AssignCommand(oCaster, ActionStartConversation(oCreature, sFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
ExecuteScript("nw_ch_acb", oCreature);
|
||||
}
|
||||
@@ -152,6 +152,8 @@ void ai_AmbientAnimations();
|
||||
|
||||
void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID)
|
||||
{
|
||||
object oMaster = GetMaster(oCreature);
|
||||
if(GetLocalInt(oMaster, AI_TARGET_MODE_ON) && GetLocalObject(oMaster, AI_TARGET_MODE_ASSOCIATE) == oCreature) return;
|
||||
if(ai_StayClose(oCreature)) return;
|
||||
// Is the target our Player has locked in dead? If so then clear it.
|
||||
if(GetIsDead(GetLocalObject(oCreature, AI_PC_LOCKED_TARGET))) DeleteLocalObject(oCreature, AI_PC_LOCKED_TARGET);
|
||||
@@ -176,21 +178,27 @@ void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID
|
||||
// the polymorph AI script.
|
||||
if(sAI != "ai_coward" && sAI != "ai_a_peaceful")
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "173", "Should we use polymorph? " +
|
||||
IntToString(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature)));
|
||||
if(AI_DEBUG)
|
||||
{
|
||||
ai_Debug("0i_actions", "181", "Should we use polymorph? Current: " +
|
||||
IntToString(GetAppearanceType(oCreature)) + " Normal: " + IntToString(ai_GetNormalAppearance(oCreature)));
|
||||
if(ai_GetIsHidden(oCreature))
|
||||
{
|
||||
ai_Debug("0i_actions", "179", "We are hidden!" +
|
||||
ai_Debug("0i_actions", "185", "We are hidden!" +
|
||||
" Can they see us? " + IntToString(ai_GetNearestIndexThatSeesUs(oCreature)));
|
||||
}
|
||||
}
|
||||
if(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature))
|
||||
if(ai_GetIsHidden(oCreature) && !ai_GetNearestIndexThatSeesUs(oCreature)) sAI = "ai_a_invisible";
|
||||
else if(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature))
|
||||
{
|
||||
sAI = "ai_a_polymorphed";
|
||||
if(!GetLocalInt(oCreature, AI_POLYMORPHED))
|
||||
{
|
||||
SetLocalInt(oCreature, AI_POLYMORPHED, TRUE);
|
||||
ai_ClearTalents(oCreature);
|
||||
ai_SetCreatureSpecialAbilityTalents(oCreature, FALSE, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
else if(ai_GetIsHidden(oCreature) && !ai_GetNearestIndexThatSeesUs(oCreature)) sAI = "ai_a_invisible";
|
||||
}
|
||||
if(sAI == "") sAI = "ai_a_default";
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "190", "********** " + GetName (oCreature) + " **********");
|
||||
@@ -211,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);
|
||||
@@ -226,11 +235,24 @@ void ai_DoMonsterCombatRound(object oMonster)
|
||||
string sAI = GetLocalString(oMonster, AI_COMBAT_SCRIPT);
|
||||
if(sAI != "ai_coward")
|
||||
{
|
||||
if(GetAppearanceType(oMonster) != ai_GetNormalAppearance(oMonster))
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "235", "Should we use polymorph? Current: " +
|
||||
IntToString(GetAppearanceType(oMonster)) + " Normal: " + IntToString(ai_GetNormalAppearance(oMonster)));
|
||||
if(ai_GetIsHidden(oMonster))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "239", "We are hidden!" +
|
||||
" Can they see us? " + IntToString(ai_GetNearestIndexThatSeesUs(oMonster)));
|
||||
}
|
||||
if(ai_GetIsHidden(oMonster) && !ai_GetNearestIndexThatSeesUs(oMonster)) sAI = "ai_invisible";
|
||||
else if(GetAppearanceType(oMonster) != ai_GetNormalAppearance(oMonster))
|
||||
{
|
||||
sAI = "ai_polymorphed";
|
||||
if(!GetLocalInt(oMonster, AI_POLYMORPHED))
|
||||
{
|
||||
SetLocalInt(oMonster, AI_POLYMORPHED, TRUE);
|
||||
ai_ClearTalents(oMonster);
|
||||
ai_SetCreatureSpecialAbilityTalents(oMonster, TRUE, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
else if(ai_GetIsHidden(oMonster) && !ai_GetNearestIndexThatSeesUs(oMonster)) sAI = "ai_invisible";
|
||||
}
|
||||
if(sAI == "") sAI = "ai_default";
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "230", "********** " + GetName (oMonster) + " **********");
|
||||
@@ -277,7 +299,7 @@ int ai_StayClose(object oCreature)
|
||||
if(fPerceptionDistance == 0.0)
|
||||
{
|
||||
fPerceptionDistance = GetLocalFloat(oMaster, AI_ASSOC_PERCEPTION_DISTANCE);
|
||||
if(fPerceptionDistance == 0.0) fPerceptionDistance = 20.0;
|
||||
if(fPerceptionDistance == 0.0) fPerceptionDistance = 25.0;
|
||||
}
|
||||
object oTarget = GetLocalObject(oCreature, AI_FOLLOW_TARGET);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = oMaster;
|
||||
@@ -389,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
|
||||
@@ -399,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;
|
||||
}
|
||||
@@ -512,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;
|
||||
@@ -521,11 +557,11 @@ int ai_MoralCheck(object oCreature)
|
||||
if(nHpPercent <= AI_HEALTH_WOUNDED)
|
||||
{
|
||||
// Debug code to look for multiple moral checks at once by one creature?
|
||||
if(GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE) == "")
|
||||
{
|
||||
SetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE, GetName(oCreature));
|
||||
ai_Debug("0i_actions", "424", GetName(oCreature) + " starting debug mode to test Moral checks!");
|
||||
}
|
||||
//if(GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE) == "")
|
||||
//{
|
||||
// SetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE, GetName(oCreature));
|
||||
// ai_Debug("0i_actions", "424", GetName(oCreature) + " starting debug mode to test Moral checks!");
|
||||
//}
|
||||
if(nHpPercent <= AI_HEALTH_BLOODY) nDC = AI_BLOODY_MORAL_DC;
|
||||
else nDC = AI_WOUNDED_MORAL_DC;
|
||||
nDC = nDC - GetLocalInt(oCreature, AI_ALLY_NUMBERS);
|
||||
@@ -681,17 +717,17 @@ void ai_DoPhysicalAttackOnBest(object oCreature, int nInMelee, int bAlwaysAtk =
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
@@ -739,17 +775,17 @@ void ai_DoPhysicalAttackOnNearest(object oCreature, int nInMelee, int bAlwaysAtk
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
@@ -796,17 +832,17 @@ void ai_DoPhysicalAttackOnLowestCR(object oCreature, int nInMelee, int bAlwaysAt
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "559", GetName(OBJECT_SELF) + " does ranged attack on weakest: " + GetName(oTarget) + "!");
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
@@ -1112,7 +1148,7 @@ void ai_ActionTryHealing(object oCreature, object oTarget)
|
||||
}
|
||||
int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "733", "Try healing: oCreature: " + GetName(oCreature) +
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1136", "Try healing: oCreature: " + GetName(oCreature) +
|
||||
" oTarget: " + GetName(oTarget) + " No Party Healing: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF)) +
|
||||
" No Self Healing: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF)) +
|
||||
" AI_I_AM_BEING_HEALED: " + IntToString(GetLocalInt(oTarget, "AI_I_AM_BEING_HEALED")) +
|
||||
@@ -1133,52 +1169,92 @@ int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE)
|
||||
oCreature != oTarget) return FALSE;
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF) &&
|
||||
oCreature == oTarget) return FALSE;
|
||||
// Undead don't heal so lets skip this for them, maybe later we can fix this.
|
||||
if(GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD) return FALSE;
|
||||
int nHpLost = ai_GetPercHPLoss(oTarget);
|
||||
// If the player is forcing a heal then we always heal.
|
||||
if(bForce && nHpLost < 100) nHpLost = 0;
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "743", "nHpLost: " + IntToString(nHpLost) +
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1160", "nHpLost: " + IntToString(nHpLost) +
|
||||
" limit: " + IntToString(ai_GetHealersHpLimit(oTarget, FALSE)));
|
||||
if(nHpLost >= ai_GetHealersHpLimit(oTarget, FALSE))
|
||||
// Check to see if we need poison, disease, or ability drain removed.
|
||||
int nEffectType;
|
||||
effect eEffect = GetFirstEffect(oTarget);
|
||||
while(GetIsEffectValid(eEffect))
|
||||
{
|
||||
// Check to see if we need poison, disease, or ability drain removed.
|
||||
int nEffectType;
|
||||
effect eEffect = GetFirstEffect(oTarget);
|
||||
while(GetIsEffectValid(eEffect))
|
||||
nEffectType = GetEffectType(eEffect);
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1168", "Checking to cure(31/32/39) nEffectType: " + IntToString(nEffectType));
|
||||
if(nEffectType == EFFECT_TYPE_DISEASE)
|
||||
{
|
||||
nEffectType = GetEffectType(eEffect);
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1094", "Checking to cure(31/32/39) nEffectType: " + IntToString(nEffectType));
|
||||
if(nEffectType == EFFECT_TYPE_DISEASE)
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1171", GetName(oTarget) + " is diseased!");
|
||||
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_DISEASED, bForce)) return TRUE;
|
||||
if(oCreature == oTarget)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1097", "I am diseased!");
|
||||
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_DISEASED, bForce)) return TRUE;
|
||||
if(oCreature == oTarget)
|
||||
{
|
||||
if(!d20()) ai_HaveCreatureSpeak(oCreature, 5, ":43:4:14:15:16:");
|
||||
SpeakString(AI_I_AM_DISEASED, TALKVOLUME_SILENT_TALK);
|
||||
}
|
||||
if(!Random(20)) ai_HaveCreatureSpeak(oCreature, 5, ":43:4:14:15:16:");
|
||||
SpeakString(AI_I_AM_DISEASED, TALKVOLUME_SILENT_TALK);
|
||||
}
|
||||
else if(nEffectType == EFFECT_TYPE_POISON)
|
||||
}
|
||||
else if(nEffectType == EFFECT_TYPE_POISON)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1181", GetName(oTarget) + " is poisoned!");
|
||||
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_POISONED, bForce)) return TRUE;
|
||||
if(oCreature == oTarget)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1107", "I am poisoned!");
|
||||
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_POISONED, bForce)) return TRUE;
|
||||
if(oCreature == oTarget)
|
||||
{
|
||||
if(!d20()) ai_HaveCreatureSpeak(oCreature, 6, ":43:4:14:15:16:19:");
|
||||
SpeakString(AI_I_AM_POISONED, TALKVOLUME_SILENT_TALK);
|
||||
}
|
||||
if(!Random(20)) ai_HaveCreatureSpeak(oCreature, 6, ":43:4:14:15:16:19:");
|
||||
SpeakString(AI_I_AM_POISONED, TALKVOLUME_SILENT_TALK);
|
||||
}
|
||||
else if(nEffectType == EFFECT_TYPE_ABILITY_DECREASE)
|
||||
}
|
||||
else if(nEffectType == EFFECT_TYPE_ABILITY_DECREASE)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1191", GetName(oTarget) + " is weak!");
|
||||
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_WEAK, bForce)) return TRUE;
|
||||
if(oCreature == oTarget)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "1117", "I am weak!");
|
||||
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_WEAK, bForce)) return TRUE;
|
||||
if(oCreature == oTarget)
|
||||
{
|
||||
if(!d20()) ai_HaveCreatureSpeak(oCreature, 3, ":43:4:5:");
|
||||
SpeakString(AI_I_AM_WEAK, TALKVOLUME_SILENT_TALK);
|
||||
}
|
||||
if(!Random(20)) ai_HaveCreatureSpeak(oCreature, 3, ":43:4:5:");
|
||||
SpeakString(AI_I_AM_WEAK, TALKVOLUME_SILENT_TALK);
|
||||
}
|
||||
eEffect = GetNextEffect(oTarget);
|
||||
}
|
||||
eEffect = GetNextEffect(oTarget);
|
||||
}
|
||||
// Everything below here is for healing.
|
||||
if(nHpLost >= ai_GetHealersHpLimit(oTarget, FALSE)) return FALSE;
|
||||
// Undead require inflict spells to heal!
|
||||
object oMaster = ai_GetPlayerMaster(oCreature);
|
||||
if(GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
|
||||
{
|
||||
// Do we have no magic on?
|
||||
if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC))
|
||||
{
|
||||
int nClass, nPosition = 1;
|
||||
string sMemorized;
|
||||
while(nPosition <= AI_MAX_CLASSES_PER_CHARACTER)
|
||||
{
|
||||
nClass = GetClassByPosition(nPosition, oCreature);
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "753", "nClass: " + IntToString(nClass));
|
||||
if(nClass == CLASS_TYPE_INVALID) break;
|
||||
sMemorized = Get2DAString("classes", "MemorizesSpells", nClass);
|
||||
// If Memorized column is "" then they are not a caster.
|
||||
if(sMemorized != "")
|
||||
{
|
||||
if(sMemorized == "1")
|
||||
{
|
||||
if(ai_CastMemorizedInflict(oCreature, oTarget, oMaster, nClass))
|
||||
{
|
||||
SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if(ai_CastKnownInflict(oCreature, oTarget, oMaster, nClass))
|
||||
{
|
||||
SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
nPosition++;
|
||||
}
|
||||
}
|
||||
// We can't heal ourselves! Can any of our allies? Lets ask.
|
||||
if(oCreature == oTarget)
|
||||
{
|
||||
SetLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT", GetLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT") + 1);
|
||||
SpeakString(AI_I_AM_WOUNDED, TALKVOLUME_SILENT_TALK);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1192,7 +1268,6 @@ int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
object oMaster = ai_GetPlayerMaster(oCreature);
|
||||
// Do we have no magic on?
|
||||
if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC))
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
@@ -115,7 +117,7 @@ void ai_Philos_SetStealth(object oMaster, object oCreature, string sAssociateTyp
|
||||
// Button action for giving commands to associates.
|
||||
void ai_DoCommand(object oPC, object oAssociate, int nCommand);
|
||||
// Button action to have associate do an action based on the target via OnPlayer Target event.
|
||||
void ai_Action(object oPC, object oAssociate);
|
||||
void ai_Action(object oPC, object oAssociate, int bPCAI = FALSE);
|
||||
// Toggles between normal ai script and special tactic ai scripts.
|
||||
void ai_AIScript(object oPC, object oAssociate, string sAssociate, int nToken);
|
||||
// Has the PC select a Trap and then place it on the ground from an associate.
|
||||
@@ -130,6 +132,10 @@ void ai_ChangeCameraView(object oPC, object oAssociate);
|
||||
void ai_OpenInventory(object oAssociate, object oPC);
|
||||
// Executes an installed plugin.
|
||||
void ai_Plugin_Execute(object oPC, string sElem, int bUser = 0);
|
||||
// Turns on oAssociate AI, Setting all event scripts.
|
||||
void ai_TurnOn(object oPC, object oAssociate, string sAssociateType);
|
||||
// Turns off oAssociate AI, Setting all event scripts.
|
||||
void ai_TurnOff(object oPC, object oAssociate, string sAssociateType);
|
||||
|
||||
int ai_CanIAttack(object oCreature)
|
||||
{
|
||||
@@ -161,7 +167,7 @@ object ai_GetNearestLockedObject(object oCreature)
|
||||
void ai_FindTheEnemy(object oCreature, object oSpeaker, object oTarget, int bMonster)
|
||||
{
|
||||
if(GetLocalInt(oCreature, AI_AM_I_SEARCHING)) return;
|
||||
if(oSpeaker == oTarget && d100() < 34)
|
||||
if(oSpeaker == oTarget && d100() < 16)
|
||||
{
|
||||
// Let them know we heard something in the distance!.
|
||||
if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK))
|
||||
@@ -232,7 +238,7 @@ void ai_FindTheEnemy(object oCreature, object oSpeaker, object oTarget, int bMon
|
||||
if(AI_DEBUG) ai_Debug("0i_associates", "176", "Moving and searching for " + GetName(oTarget));
|
||||
SetActionMode(oCreature, ACTION_MODE_DETECT, TRUE);
|
||||
ActionMoveToLocation(GetLocation(oTarget), FALSE);
|
||||
//ActionMoveToObject(oTarget, FALSE, AI_RANGE_MELEE);
|
||||
//ActionMoveToObject(oTarget, FALSE, AI_RANGE_MELEE);
|
||||
AssignCommand(oCreature, ActionDoCommand(DeleteLocalInt(oCreature, AI_AM_I_SEARCHING)));
|
||||
return;
|
||||
}
|
||||
@@ -519,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -769,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);
|
||||
@@ -832,10 +856,10 @@ 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(sPerception, TALKVOLUME_SILENT_TALK);
|
||||
SpeakString(AI_I_SEE_AN_ENEMY, TALKVOLUME_SILENT_TALK);
|
||||
ai_StartMonsterCombat(oCreature);
|
||||
}
|
||||
else ai_FindTheEnemy(oCreature, oLastPerceived, oLastPerceived, TRUE);
|
||||
@@ -919,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();
|
||||
@@ -1903,18 +1944,20 @@ void ai_DoCommand(object oPC, object oAssociate, int nCommand)
|
||||
}
|
||||
}
|
||||
}
|
||||
void ai_Action(object oPC, object oAssociate)
|
||||
void ai_Action(object oPC, object oAssociate, int bPCAI = FALSE)
|
||||
{
|
||||
if(oPC == oAssociate)
|
||||
{
|
||||
DeleteLocalObject(oPC, "NW_ASSOCIATE_COMMAND");
|
||||
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION_ALL");
|
||||
ai_SendMessages("Select an action for the party.", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate);
|
||||
SetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE, oAssociate);
|
||||
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION");
|
||||
SetLocalInt(oPC, AI_TARGET_MODE_ON, TRUE);
|
||||
if(!GetLocalInt(GetModule(), AI_USING_PRC) && bPCAI) ai_TurnOn(oPC, oPC, "pc");
|
||||
ai_SendMessages("Select an action for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
|
||||
@@ -2139,6 +2182,7 @@ void ai_ChangeCameraView(object oPC, object oAssociate)
|
||||
{
|
||||
SetLocalObject(oPC, "AI_CAMERA_ON_ASSOCIATE", oAssociate);
|
||||
AttachCamera(oPC, oAssociate);
|
||||
if(!ai_GetIsCharacter(oAssociate)) ai_Action(oPC, oAssociate, TRUE);
|
||||
}
|
||||
}
|
||||
void ai_SelectCameraView(object oPC)
|
||||
@@ -2190,3 +2234,47 @@ void ai_Plugin_Execute(object oPC, string sElem, int bUser = 0)
|
||||
ExecuteScript(sScript, oPC);
|
||||
}
|
||||
}
|
||||
void ai_TurnOn(object oPC, object oTarget, string sAssociateType)
|
||||
{
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ai_tooltip", " AI On");
|
||||
ai_SendMessages("AI turned on for " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC);
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "xx_pc_1_hb");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_NOTICE, "xx_pc_2_percept");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "xx_pc_3_endround");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "xx_pc_4_convers");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "xx_pc_5_phyatked");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "xx_pc_6_damaged");
|
||||
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DEATH, "");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "xx_pc_8_disturb");
|
||||
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
|
||||
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_RESTED, "");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "xx_pc_b_castat");
|
||||
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "xx_pc_e_blocked");
|
||||
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "");
|
||||
// This sets the script for the PC to run AI based on class.
|
||||
ai_SetAssociateAIScript(oTarget, FALSE);
|
||||
// Set so PC can hear associates talking in combat.
|
||||
ai_SetListeningPatterns(oTarget);
|
||||
}
|
||||
void ai_TurnOff(object oPC, object oAssociate, string sAssociateType)
|
||||
{
|
||||
ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ai_tooltip", " AI Off");
|
||||
ai_SendMessages("AI Turned off for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC);
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_NOTICE, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "");
|
||||
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DEATH, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "");
|
||||
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
|
||||
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_RESTED, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "");
|
||||
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "");
|
||||
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "");
|
||||
DeleteLocalInt(oAssociate, "AI_I_AM_BEING_HEALED");
|
||||
DeleteLocalString(oAssociate, "AIScript");
|
||||
ai_ClearCreatureActions();
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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:07.20.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
|
||||
@@ -18,7 +18,7 @@ const string PHILOS_VERSION = "Philos' Enhancing Player System (PEPS) version:07
|
||||
// This will only work if you are using the PEPS menu system.
|
||||
const int AI_DEBUG = FALSE;
|
||||
// Defines if we are compiling for single player or a server. Always on for servers!
|
||||
const int AI_SERVER = FALSE;
|
||||
const int AI_SERVER = TRUE;
|
||||
// The number of classes allowed for a creature to take in the server/module.
|
||||
const int AI_MAX_CLASSES_PER_CHARACTER = 8;
|
||||
// Taunts cool down time before the AI attemps another Taunt.
|
||||
@@ -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;
|
||||
@@ -141,7 +146,9 @@ const string AI_EFFECT_ICON_NUI = "ai_effect_icon_nui";
|
||||
// The following constants are core constants and changing any of these without
|
||||
// understanding the whole system could cause unforseen results.
|
||||
// CHANGE AT YOUR OWN RISK.
|
||||
// Variable used to asave a monster object for changing.
|
||||
// Variable used to check if the module is running as a server.
|
||||
const string AI_IS_SERVER = "AI_IS_SERVER";
|
||||
// Variable used to save a monster object for changing.
|
||||
const string AI_MONSTER_OBJECT = "AI_MONSTER_OBJECT";
|
||||
// Variable used to save a monsters json for changing.
|
||||
const string AI_MONSTER_JSON = "AI_MONSTER_JSON";
|
||||
@@ -160,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.
|
||||
@@ -219,7 +226,6 @@ const string AI_I_AM_DEAD = "AI_I_AM_DEAD";
|
||||
const string AI_I_AM_DISEASED = "AI_I_AM_DISEASED";
|
||||
const string AI_I_AM_POISONED = "AI_I_AM_POISONED";
|
||||
const string AI_I_AM_WEAK = "AI_I_AM_WEAK";
|
||||
const int AI_ALLY_SEES_AN_ENEMY = 1;
|
||||
const int AI_ALLY_HEARD_AN_ENEMY = 2;
|
||||
const int AI_ALLY_ATKED_BY_WEAPON = 3;
|
||||
const int AI_ALLY_ATKED_BY_SPELL = 4;
|
||||
@@ -228,6 +234,7 @@ const int AI_ALLY_IS_DEAD = 6;
|
||||
const int AI_ALLY_IS_DISEASED = 7;
|
||||
const int AI_ALLY_IS_POISONED = 8;
|
||||
const int AI_ALLY_IS_WEAK = 9;
|
||||
const int AI_ALLY_SEES_AN_ENEMY = 10;
|
||||
const string AI_MY_TARGET = "AI_MY_TARGET";
|
||||
// Constant used by monsters to reduce checks while searching for unseen targets.
|
||||
const string AI_AM_I_SEARCHING = "AI_AM_I_SEARCHING";
|
||||
@@ -238,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;
|
||||
@@ -255,6 +264,8 @@ const string AI_ATTACKED_PHYSICAL = "AI_ATTACKED_PHYSICAL";
|
||||
const string AI_ATTACKED_SPELL = "AI_ATTACKED_SPELL";
|
||||
// Variable name used to keep track of a creatures normal polymorph form.
|
||||
const string AI_NORMAL_FORM = "AI_NORMAL_FORM";
|
||||
// Variable name used to have associates defined as Polymorphed.
|
||||
const string AI_POLYMORPHED = "AI_POLYMORPHED";
|
||||
// Variable name used to keep track if a creature has been buffed yet.
|
||||
const string AI_CASTER_BUFFS_SET = "AI_CASTER_BUFFS_SET";
|
||||
// Variable name used to keep track of rounds in combat for a custom ai script.
|
||||
@@ -320,6 +331,7 @@ const int AI_CONDITION_CONFUSED = 0x00020000;
|
||||
const int AI_CONDITION_CURSE = 0x00040000;
|
||||
const int AI_CONDITION_PARALYZE = 0x00080000;
|
||||
const int AI_CONDITION_DOMINATED = 0x00100000;
|
||||
const int AI_CONDITION_DEAD = 0x00200000;
|
||||
// Database constants for Associate modes.
|
||||
const string AI_MODE_DB_TABLE = "AI_MODE_DB_TABLE";
|
||||
// Bitwise constants for Associate modes that are used with Get/SetAssociateMode().
|
||||
@@ -394,30 +406,31 @@ const int AI_MAGIC_NO_SPONTANEOUS_CURE = 0x00000800; // Caster will stop using s
|
||||
const string AI_NO_NUI_SAVE = "AI_NO_NUI_SAVE";
|
||||
// Bitwise menu constants for Widget buttons that are used with Get/SetAssociateWidgetButtons().
|
||||
const string sWidgetButtonsVarname = "ASSOCIATE_WIDGET_BUTTONS";
|
||||
const int BTN_WIDGET_OFF = 0x00000001; // Removes the widget from the screen, For PC it removes all associates.
|
||||
const int BTN_WIDGET_LOCK = 0x00000002; // Locks the widget to the current coordinates.
|
||||
const int BTN_CMD_GUARD = 0x00000004; // Command associates to Guard Me. PC widget only.
|
||||
const int BTN_CMD_FOLLOW = 0x00000008; // Command associates to Follow. PC widget only.
|
||||
const int BTN_CMD_HOLD = 0x00000010; // Command associates to Stand Ground. PC widget only.
|
||||
const int BTN_CMD_ATTACK = 0x00000020; // Command associates to Attack Nearest. PC widget only.
|
||||
const int BTN_BUFF_REST = 0x00000040; // Buffs with long duration spells after resting. Associate widget only.
|
||||
const int BTN_BUFF_SHORT = 0x00000080; // Buffs with short duration spells.
|
||||
const int BTN_BUFF_LONG = 0x00000100; // Buffs with long duration spells.
|
||||
const int BTN_BUFF_ALL = 0x00000200; // Buffs with all spells.
|
||||
const int BTN_CMD_ACTION = 0x00000400; // Command associate to do an action.
|
||||
const int BTN_CMD_GHOST_MODE = 0x00000800; // Toggle's associates ghost mode.
|
||||
const int BTN_CMD_AI_SCRIPT = 0x00001000; // Toggle's special tactics ai scripts.
|
||||
const int BTN_CMD_PLACE_TRAP = 0x00002000; // A trapper may place traps.
|
||||
const int BTN_CMD_CAMERA = 0x00004000; // Places camera view on associate.
|
||||
const int BTN_CMD_INVENTORY = 0x00008000; // Opens inventory of associate.
|
||||
const int BTN_CMD_FAMILIAR = 0x00010000; // Summons familiar.
|
||||
const int BTN_CMD_COMPANION = 0x00020000; // Summons Companion.
|
||||
const int BTN_CMD_SEARCH = 0x00040000; // Command all associates to use search mode. PC widget only.
|
||||
const int BTN_CMD_STEALTH = 0x00080000; // Command all associates to use stealth mode. PC widget only.
|
||||
const int BTN_CMD_SCOUT = 0x00100000; // Command associate to scout ahead of the part.
|
||||
const int BTN_CMD_SPELL_WIDGET = 0x00200000; // Allows adding or removing spells from Spell Widget.
|
||||
const int BTN_CMD_JUMP_TO = 0x00400000; // Player can make associates jump to them.
|
||||
const int BTN_WIDGET_VERTICAL = 0x80000000; // Widget will be displayed vertical.
|
||||
const int BTN_WIDGET_OFF = 0x00000001; // Removes the widget from the screen, For PC it removes all associates.
|
||||
const int BTN_WIDGET_LOCK = 0x00000002; // Locks the widget to the current coordinates.
|
||||
const int BTN_CMD_GUARD = 0x00000004; // Command associates to Guard Me. PC widget only.
|
||||
const int BTN_CMD_FOLLOW = 0x00000008; // Command associates to Follow. PC widget only.
|
||||
const int BTN_CMD_HOLD = 0x00000010; // Command associates to Stand Ground. PC widget only.
|
||||
const int BTN_CMD_ATTACK = 0x00000020; // Command associates to Attack Nearest. PC widget only.
|
||||
const int BTN_BUFF_REST = 0x00000040; // Buffs with long duration spells after resting. Associate widget only.
|
||||
const int BTN_BUFF_SHORT = 0x00000080; // Buffs with short duration spells.
|
||||
const int BTN_BUFF_LONG = 0x00000100; // Buffs with long duration spells.
|
||||
const int BTN_BUFF_ALL = 0x00000200; // Buffs with all spells.
|
||||
const int BTN_CMD_ACTION = 0x00000400; // Command associate to do an action.
|
||||
const int BTN_CMD_GHOST_MODE = 0x00000800; // Toggle's associates ghost mode.
|
||||
const int BTN_CMD_AI_SCRIPT = 0x00001000; // Toggle's special tactics ai scripts.
|
||||
const int BTN_CMD_PLACE_TRAP = 0x00002000; // A trapper may place traps.
|
||||
const int BTN_CMD_CAMERA = 0x00004000; // Places camera view on associate.
|
||||
const int BTN_CMD_INVENTORY = 0x00008000; // Opens inventory of associate.
|
||||
const int BTN_CMD_FAMILIAR = 0x00010000; // Summons familiar.
|
||||
const int BTN_CMD_COMPANION = 0x00020000; // Summons Companion.
|
||||
const int BTN_CMD_SEARCH = 0x00040000; // Command all associates to use search mode. PC widget only.
|
||||
const int BTN_CMD_STEALTH = 0x00080000; // Command all associates to use stealth mode. PC widget only.
|
||||
const int BTN_CMD_SCOUT = 0x00100000; // Command associate to scout ahead of the part.
|
||||
const int BTN_CMD_SPELL_WIDGET = 0x00200000; // Allows adding or removing spells from Spell Widget.
|
||||
const int BTN_CMD_JUMP_TO = 0x00400000; // Player can make associates jump to them.
|
||||
const int BTN_ASSOC_WIDGETS_OFF = 0x00800000; // Turns all associate widgets on/off.
|
||||
const int BTN_WIDGET_VERTICAL = 0x80000000; // Widget will be displayed vertical.
|
||||
// Bitwise menu constants for Associate AI buttons that are used with Get/SetAssociateAIButtons().
|
||||
const string sAIButtonsVarname = "ASSOCIATE_AI_BUTTONS";
|
||||
const int BTN_AI_FOR_PC = 0x00000001; // PC use AI. PC widget only.
|
||||
@@ -521,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
|
||||
@@ -548,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.
|
||||
@@ -568,6 +585,12 @@ const string AI_MODULE_GUI_EVENT = "AI_MODULE_GUI_EVENT";
|
||||
const string AI_TARGET_MODE = "AI_TARGET_MODE";
|
||||
// Variable used on the player to define which associate triggered the OnPlayer Target.
|
||||
const string AI_TARGET_ASSOCIATE = "AI_TARGET_ASSOCIATE";
|
||||
// Variable use on the player to define if the player is using target mode on an associate.
|
||||
const string AI_TARGET_MODE_ON = "AI_TARGET_MODE_ON";
|
||||
// Variable used on the player to define what associate has Target Mode set on it.
|
||||
const string AI_TARGET_MODE_ASSOCIATE = "AI_TARGET_MODE_ASSOCIATE";
|
||||
// Variable used on a creature to define how long ago their immunities were saved.
|
||||
const string sIPTimeStampVarname = "AI_IP_TIMESTAMP";
|
||||
// Bitwise constants for immune damage item properties that is used with Get/SetItemProperty().
|
||||
const string sIPImmuneVarname = "AI_IP_IMMUNE";
|
||||
// Bitwise constants for resisted damage item properties that is used with Get/SetItemProperty().
|
||||
@@ -585,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.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_constants"
|
||||
#include "0i_nui"
|
||||
void ai_SetupModuleGUIEvents(object oCreature)
|
||||
void ai_SetupModuleGUIEvents()
|
||||
{
|
||||
object oModule = GetModule();
|
||||
string sModuleGUIEvents = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_GUIEVENT);
|
||||
|
||||
@@ -25,6 +25,8 @@ const string AI_DM_TABLE = "DM_TABLE";
|
||||
// Sets PEPS RULES from the database to the module.
|
||||
// Creates default rules if they do not exist.
|
||||
void ai_SetAIRules();
|
||||
// Returns TRUE if the module is being run as a server.
|
||||
int ai_GetIsServer();
|
||||
// Returns TRUE if oCreature is controlled by a player.
|
||||
int ai_GetIsCharacter(object oCreature);
|
||||
// Returns TRUE if oCreature is controlled by a dungeon master.
|
||||
@@ -32,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.
|
||||
@@ -129,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));
|
||||
@@ -215,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);
|
||||
@@ -307,13 +318,17 @@ void ai_SetAIRules()
|
||||
SetLocalInt(oModule, sDMAIAccessVarname, bValue);
|
||||
}
|
||||
}
|
||||
int ai_GetIsServer()
|
||||
{
|
||||
return GetLocalInt(GetModule(), AI_IS_SERVER) || AI_SERVER;
|
||||
}
|
||||
int ai_GetIsCharacter(object oCreature)
|
||||
{
|
||||
return (GetIsPC(oCreature) && !GetIsDM(oCreature) && !GetIsDMPossessed(oCreature));
|
||||
return (GetIsPC(oCreature) && !GetIsDM(oCreature) && !GetIsDMPossessed(oCreature) && !GetIsPlayerDM(oCreature));
|
||||
}
|
||||
int ai_GetIsDungeonMaster(object oCreature)
|
||||
{
|
||||
return (GetIsDM(oCreature) || GetIsDMPossessed(oCreature));
|
||||
return (GetIsDM(oCreature) || GetIsDMPossessed(oCreature) || GetIsPlayerDM(oCreature));
|
||||
}
|
||||
object ai_GetPlayerMaster(object oAssociate)
|
||||
{
|
||||
@@ -322,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);
|
||||
@@ -862,12 +887,14 @@ void ai_SetupAIData(object oPlayer, object oAssociate, string sAssociateType)
|
||||
// We keep it for now as we don't want to move other data.
|
||||
jAIData = JsonArrayInsert(jAIData, JsonInt(11)); // 7 - Associate Perception DistanceDistance.
|
||||
SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION, 11);
|
||||
SetLocalFloat(oAssociate, AI_ASSOC_PERCEPTION_DISTANCE, 20.0);
|
||||
SetLocalFloat(oAssociate, AI_ASSOC_PERCEPTION_DISTANCE, 25.0);
|
||||
jAIData = JsonArrayInsert(jAIData, JsonString("")); // 8 - Associate Combat Tactics.
|
||||
jAIData = JsonArrayInsert(jAIData, JsonFloat(20.0)); // 9 - Open Doors check range.
|
||||
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)
|
||||
@@ -979,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();
|
||||
@@ -1080,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");
|
||||
@@ -1140,7 +1177,7 @@ void ai_SetupDMData(object oPlayer, string sName)
|
||||
void ai_CheckDMData(object oPlayer)
|
||||
{
|
||||
//ai_Debug("0i_main", "898", "Checking data for DM: " + GetName(oPlayer));
|
||||
string sName = ai_RemoveIllegalCharacters(GetName(oPlayer));
|
||||
string sName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPlayer)));
|
||||
// ********** Buttons **********
|
||||
json jButtons = ai_GetCampaignDbJson("buttons", sName, AI_DM_TABLE);
|
||||
// if there is no saved AImodes then set the defaults.
|
||||
@@ -1241,7 +1278,7 @@ json ai_CheckOldPluginJson(object oPC)
|
||||
json ai_UpdatePluginsForPC(object oPC)
|
||||
{
|
||||
// Check if the server is running or single player.
|
||||
if(!AI_SERVER) return ai_CheckOldPluginJson(oPC);
|
||||
if(!ai_GetIsServer()) return ai_CheckOldPluginJson(oPC);
|
||||
int nJsonType, nCounter, nIndex, bWidget, bAllow;
|
||||
string sScript, sName, sIcon;
|
||||
json jServerPlugins = ai_GetCampaignDbJson("plugins");
|
||||
@@ -1283,7 +1320,7 @@ json ai_UpdatePluginsForPC(object oPC)
|
||||
json ai_UpdatePluginsForDM(object oPC)
|
||||
{
|
||||
int nJsonType, nCounter, nIndex, bWidget, bAllow;
|
||||
string sName, sIcon, sDbName = ai_RemoveIllegalCharacters(GetName(oPC));
|
||||
string sName, sIcon, sDbName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oPC)));
|
||||
json jServerPlugins = ai_GetCampaignDbJson("plugins");
|
||||
ai_CheckDMDataAndInitialize(oPC);
|
||||
json jDMPlugin, jDMPlugins = ai_GetCampaignDbJson("plugins", sDbName, AI_DM_TABLE);
|
||||
@@ -1323,7 +1360,7 @@ void ai_StartupPlugins(object oPC)
|
||||
int bUpdatePlugins;
|
||||
string sScript;
|
||||
json jPlugins;
|
||||
if(GetIsDM(oPC)) jPlugins = ai_UpdatePluginsForDM(oPC);
|
||||
if(ai_GetIsDungeonMaster(oPC)) jPlugins = ai_UpdatePluginsForDM(oPC);
|
||||
else jPlugins = ai_UpdatePluginsForPC(oPC);
|
||||
// We delete this so each mod can be added that legally loads.
|
||||
DeleteLocalJson(GetModule(), AI_MONSTER_MOD_JSON);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -268,7 +268,7 @@ void ai_CreateDMOptionsNUI(object oPC)
|
||||
int nMonsterAI = (ResManGetAliasFor("ai_default", RESTYPE_NCS) != "");
|
||||
int nAssociateAI = (ResManGetAliasFor("ai_a_default", RESTYPE_NCS) != "");
|
||||
string sText = " [Single player]";
|
||||
if(AI_SERVER) sText = " [Server]";
|
||||
if(ai_GetIsServer()) sText = " [Server]";
|
||||
// ************************************************************************* Width / Height
|
||||
// Row 1 ******************************************************************* 500 / 73
|
||||
json jRow = JsonArrayInsert(JsonArray(), NuiSpacer());
|
||||
@@ -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));
|
||||
@@ -876,6 +889,9 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
jRow = CreateLabel(JsonArray(), "Having a check next to a button will remove that button from the players menus.", "lbl_info2", 636.0, 15.0);
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 4 ******************************************************************* 575 / 162
|
||||
jRow = CreateButtonImage(jRow, "ir_invite", "btn_toggle_assoc_widget", 35.0f, 35.0f, 0.0, "btn_toggle_assoc_widget_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_toggle_assoc_widget", 25.0, 20.0, "btn_toggle_assoc_widget_tooltip");
|
||||
|
||||
jRow = CreateButtonImage(JsonArray(), "ir_action", "btn_cmd_action", 35.0f, 35.0f, 0.0, "btn_cmd_action_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_cmd_action", 25.0, 20.0, "btn_cmd_action_tooltip");
|
||||
|
||||
@@ -903,10 +919,11 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
jRow = CreateButtonImage(jRow, "ir_scommand", "btn_cmd_ai_script", 35.0f, 35.0f, 0.0, "btn_cmd_ai_script_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_cmd_ai_script", 25.0, 20.0, "btn_cmd_ai_script_tooltip");
|
||||
|
||||
jRow = CreateButtonImage(jRow, "isk_settrap", "btn_cmd_place_trap", 35.0f, 35.0f, 0.0, "btn_cmd_place_trap_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_cmd_place_trap", 25.0, 20.0, "btn_cmd_place_trap_tooltip");
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 5 ******************************************************************* 575 / 205
|
||||
jRow = CreateButtonImage(jRow, "isk_settrap", "btn_cmd_place_trap", 35.0f, 35.0f, 0.0, "btn_cmd_place_trap_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_cmd_place_trap", 25.0, 20.0, "btn_cmd_place_trap_tooltip");
|
||||
|
||||
jRow = CreateButtonImage(JsonArray(), "isk_spellcraft", "btn_quick_widget", 35.0f, 35.0f, 0.0, "btn_quick_widget_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_quick_widget", 25.0, 20.0, "btn_quick_widget_tooltip");
|
||||
|
||||
@@ -934,10 +951,10 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
jRow = CreateButtonImage(jRow, "ir_examine", "btn_camera", 35.0f, 35.0f, 0.0, "btn_camera_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_camera", 25.0, 20.0, "btn_camera_tooltip");
|
||||
|
||||
jRow = CreateButtonImage(jRow, "ir_pickup", "btn_inventory", 35.0f, 35.0f, 0.0, "btn_inventory_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_inventory", 25.0, 20.0, "btn_inventory_tooltip");
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 6 ******************************************************************* 575 / 248
|
||||
jRow = CreateButtonImage(jRow, "ir_pickup", "btn_inventory", 35.0f, 35.0f, 0.0, "btn_inventory_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_inventory", 25.0, 20.0, "btn_inventory_tooltip");
|
||||
|
||||
jRow = CreateButtonImage(JsonArray(), "ife_familiar", "btn_familiar", 35.0f, 35.0f, 0.0, "btn_familiar_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_familiar", 25.0, 20.0, "btn_familiar_tooltip");
|
||||
@@ -966,10 +983,10 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
jRow = CreateButtonImage(jRow, "ir_open", "btn_open_door", 35.0f, 35.0f, 0.0, "btn_open_door_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_open_door", 25.0, 20.0, "btn_open_door_tooltip");
|
||||
|
||||
jRow = CreateButtonImage(jRow, "isk_distrap", "btn_traps", 35.0f, 35.0f, 0.0, "btn_traps_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_traps", 25.0, 20.0, "btn_traps_tooltip");
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 7 ******************************************************************* 575 / 291
|
||||
jRow = CreateButtonImage(jRow, "isk_distrap", "btn_traps", 35.0f, 35.0f, 0.0, "btn_traps_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_traps", 25.0, 20.0, "btn_traps_tooltip");
|
||||
|
||||
jRow = CreateButtonImage(JsonArray(), "isk_olock", "btn_pick_locks", 35.0f, 35.0f, 0.0, "btn_pick_locks_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_pick_locks", 25.0, 20.0, "btn_pick_locks_tooltip");
|
||||
@@ -998,10 +1015,11 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
jRow = CreateButtonImage(jRow, "isk_heal", "btn_heal_out", 35.0f, 35.0f, 0.0, "btn_heal_out_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_heal_out", 25.0, 20.0, "btn_heal_out_tooltip");
|
||||
|
||||
jRow = CreateButtonImage(jRow, "dm_heal", "btn_heal_in", 35.0f, 35.0f, 0.0, "btn_heal_in_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_heal_in", 25.0, 20.0, "btn_heal_in_tooltip");
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 8 ******************************************************************* 575 / 334
|
||||
jRow = CreateButtonImage(jRow, "dm_heal", "btn_heal_in", 35.0f, 35.0f, 0.0, "btn_heal_in_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_heal_in", 25.0, 20.0, "btn_heal_in_tooltip");
|
||||
|
||||
jRow = CreateButtonImage(JsonArray(), "ir_heal", "btn_heals_onoff", 35.0f, 35.0f, 0.0, "btn_heals_onoff_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_heals_onoff", 25.0, 20.0, "btn_heals_onoff_tooltip");
|
||||
|
||||
@@ -1023,7 +1041,6 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
jRow = CreateButtonImage(jRow, "ir_dmchat", "btn_perc_range", 35.0f, 35.0f, 0.0, "btn_perc_range_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "", "chbx_perc_range", 25.0, 20.0, "btn_perc_range_tooltip");
|
||||
|
||||
// Add row to the column.
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
float fHeight = 334.0;
|
||||
// Get the window location to restore it from the database.
|
||||
@@ -1049,6 +1066,7 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
// Row 2 & 3 Labels.
|
||||
// Load all the buttons states.
|
||||
//int bAIWidgetLock = ai_GetDMWAccessButton(BTN_WIDGET_LOCK);
|
||||
int bAssocWidgetOff = ai_GetDMWAccessButton(BTN_ASSOC_WIDGETS_OFF);
|
||||
int bCmdAction = ai_GetDMWAccessButton(BTN_CMD_ACTION);
|
||||
int bCmdGuard = ai_GetDMWAccessButton(BTN_CMD_GUARD);
|
||||
int bCmdHold = ai_GetDMWAccessButton(BTN_CMD_HOLD);
|
||||
@@ -1101,6 +1119,12 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
SetLocalInt(oPC, "CHBX_SKIP", TRUE);
|
||||
DelayCommand(2.0, DeleteLocalInt(oPC, "CHBX_SKIP"));
|
||||
// Row 4
|
||||
NuiSetBind(oPC, nToken, "chbx_toggle_assoc_widget_check", JsonBool (bCmdAction));
|
||||
NuiSetBindWatch(oPC, nToken, "chbx_toggle_assoc_widget_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_toggle_assoc_widget_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_toggle_assoc_widget_event", JsonBool (TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_toggle_assoc_widget_tooltip", JsonString(" Associate widgets"));
|
||||
|
||||
NuiSetBind(oPC, nToken, "chbx_cmd_action_check", JsonBool (bCmdAction));
|
||||
NuiSetBindWatch(oPC, nToken, "chbx_cmd_action_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_cmd_action_event", JsonBool(TRUE));
|
||||
@@ -1154,13 +1178,13 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
NuiSetBind(oPC, nToken, "chbx_cmd_ai_script_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_cmd_ai_script_event", JsonBool (TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_cmd_ai_script_tooltip", JsonString(" Combat Tactics button"));
|
||||
|
||||
// Row 5
|
||||
NuiSetBind(oPC, nToken, "chbx_cmd_place_trap_check", JsonBool (bCmdPlacetrap));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_cmd_place_trap_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_cmd_place_trap_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_cmd_place_trap_event", JsonBool (TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_cmd_place_trap_tooltip", JsonString (" Place Trap button"));
|
||||
// Row 5
|
||||
|
||||
NuiSetBind(oPC, nToken, "chbx_quick_widget_check", JsonBool (bSpellWidget));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_quick_widget_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_quick_widget_event", JsonBool(TRUE));
|
||||
@@ -1214,13 +1238,13 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
NuiSetBind(oPC, nToken, "chbx_camera_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_camera_event", JsonBool (TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_camera_tooltip", JsonString(" Change Camera button"));
|
||||
|
||||
// Row 6
|
||||
NuiSetBind(oPC, nToken, "chbx_inventory_check", JsonBool (bInventory));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_inventory_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_inventory_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_inventory_event", JsonBool (TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_inventory_tooltip", JsonString(" Open Inventory button"));
|
||||
// Row 6
|
||||
|
||||
NuiSetBind(oPC, nToken, "chbx_familiar_check", JsonBool(bBtnFamiliar));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_familiar_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_familiar_event", JsonBool(TRUE));
|
||||
@@ -1274,13 +1298,13 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
NuiSetBind(oPC, nToken, "chbx_open_door_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_open_door_event", JsonBool(TRUE));
|
||||
NuiSetBind (oPC, nToken, "btn_open_door_tooltip", JsonString(" Open Door button"));
|
||||
|
||||
// Row 7
|
||||
NuiSetBind(oPC, nToken, "chbx_traps_check", JsonBool(bTraps));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_traps_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_traps_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_traps_event", JsonBool(TRUE));
|
||||
NuiSetBind (oPC, nToken, "btn_traps_tooltip", JsonString(" Disable Traps button"));
|
||||
// Row 7
|
||||
|
||||
NuiSetBind(oPC, nToken, "chbx_pick_locks_check", JsonBool(bPickLocks));
|
||||
NuiSetBindWatch(oPC, nToken, "chbx_pick_locks_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_pick_locks_event", JsonBool(TRUE));
|
||||
@@ -1334,13 +1358,13 @@ void ai_CreateDMWidgetManagerNUI(object oPC)
|
||||
NuiSetBind(oPC, nToken, "chbx_heal_out_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_heal_out_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_heal_out_tooltip", JsonString(" Heal Out of Combat button"));
|
||||
|
||||
// Row 8
|
||||
NuiSetBind(oPC, nToken, "chbx_heal_in_check", JsonBool(bHealIn));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_heal_in_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_heal_in_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_heal_in_event", JsonBool (TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_heal_in_tooltip", JsonString(" Heal In Combat button"));
|
||||
// Row 8
|
||||
|
||||
NuiSetBind(oPC, nToken, "chbx_heals_onoff_check", JsonBool(bSelfHealOnOff));
|
||||
NuiSetBindWatch (oPC, nToken, "chbx_heals_onoff_check", TRUE);
|
||||
NuiSetBind(oPC, nToken, "chbx_heals_onoff_event", JsonBool(TRUE));
|
||||
|
||||
@@ -7,15 +7,18 @@
|
||||
#include "x2_inc_switches"
|
||||
#include "0i_associates"
|
||||
#include "0i_menus"
|
||||
#include "0i_menus_dm"
|
||||
#include "0i_player_target"
|
||||
#include "0i_gui_events"
|
||||
// Add to nw_c2_default9 OnSpawn event script of monsters and
|
||||
int ai_OnMonsterSpawn(object oCreature);
|
||||
// Add to nw_ch_ac9 OnSpawn event script of henchman.
|
||||
void ai_OnAssociateSpawn(object oCreature);
|
||||
// Run all of the players starting scripts.
|
||||
// Run all of the game setup scripts and build for PC.
|
||||
// If oPC is passed as Invalid then it will get the firt PC in the game.
|
||||
void ai_CheckPCStart(object oPC = OBJECT_INVALID);
|
||||
// Run all of the games setup scripts and build for DM.
|
||||
void ai_CheckDMStart(object oDM);
|
||||
// Checks to see if we should change the monster via Json.
|
||||
int ai_ChangeMonster(object oCreature, object oModule);
|
||||
// Checks to see if we should change the associate via Json.
|
||||
@@ -45,7 +48,7 @@ int ai_OnMonsterSpawn(object oCreature)
|
||||
int nInfiniteDungeons;
|
||||
int nPRC = GetLocalInt(oModule, AI_USING_PRC);
|
||||
// If you are running a server this will not affect the module.
|
||||
if(!AI_SERVER)
|
||||
if(!ai_GetIsServer())
|
||||
{
|
||||
ai_CheckPCStart();
|
||||
string sModuleName = GetModuleName();
|
||||
@@ -107,7 +110,7 @@ void ai_OnAssociateSpawn(object oCreature)
|
||||
SetLocalInt(oCreature, AI_ONSPAWN_EVENT, TRUE);
|
||||
int bPRC = GetLocalInt(GetModule(), AI_USING_PRC);
|
||||
// If you are running a server this will not affect the module.
|
||||
if(!AI_SERVER)
|
||||
if(!ai_GetIsServer())
|
||||
{
|
||||
if(bPRC) ai_SetPRCAssociateEventScripts(oCreature);
|
||||
}
|
||||
@@ -117,8 +120,17 @@ void ai_OnAssociateSpawn(object oCreature)
|
||||
// We change this script so we can setup permanent summons on/off.
|
||||
// If you don't use this you may remove the next three lines.
|
||||
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH);
|
||||
SetLocalString(oCreature, "AI_ON_DEATH", sScript);
|
||||
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_ch_7_ondeath");
|
||||
// If our script is set in the OnDeath event then don't save as secondary.
|
||||
if(sScript != "0e_ch_7_ondeath")
|
||||
{
|
||||
SetLocalString(oCreature, "AI_ON_DEATH", sScript);
|
||||
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_ch_7_ondeath");
|
||||
}
|
||||
else if(GetLocalString(oCreature, "AI_ON_DEATH") == "0e_ch_7_ondeath")
|
||||
{
|
||||
// If we have somehow saved our death script then change to default.
|
||||
SetLocalString(oCreature, "AI_ON_DEATH", "nw_ch_ac7");
|
||||
}
|
||||
}
|
||||
// Initialize Associate modes for basic use.
|
||||
ai_SetListeningPatterns(oCreature);
|
||||
@@ -147,12 +159,28 @@ void ai_CheckPCStart(object oPC = OBJECT_INVALID)
|
||||
ai_SetAIRules();
|
||||
ai_CheckAssociateData(oPC, oPC, "pc");
|
||||
ai_StartupPlugins(oPC);
|
||||
ai_SetupPlayerTarget(oPC);
|
||||
ai_SetupModuleGUIEvents(oPC);
|
||||
ai_SetupPlayerTarget();
|
||||
ai_SetupModuleGUIEvents();
|
||||
ai_CreateWidgetNUI(oPC, oPC);
|
||||
ai_SetNormalAppearance(oPC);
|
||||
}
|
||||
}
|
||||
void ai_CheckDMStart(object oDM)
|
||||
{
|
||||
if(!NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI))
|
||||
{
|
||||
object oModule = GetModule();
|
||||
// Do PRC check and save variable to the module.
|
||||
if(ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS) != "")
|
||||
SetLocalInt(oModule, AI_USING_PRC, TRUE);
|
||||
ai_SetAIRules();
|
||||
ai_CheckDMData(oDM);
|
||||
ai_StartupPlugins(oDM);
|
||||
ai_SetupPlayerTarget();
|
||||
ai_SetupModuleGUIEvents();
|
||||
ai_CreateDMWidgetNUI(oDM);
|
||||
}
|
||||
}
|
||||
void ai_CopyMonster(object oCreature, object oModule)
|
||||
{
|
||||
// After setting the monster lets see if we should copy it.
|
||||
@@ -179,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))
|
||||
@@ -188,6 +217,12 @@ void ai_CreateMonster(json jCreature, location lLocation, object oModule)
|
||||
} */
|
||||
if(AI_DEBUG) ai_Debug("0i_module", "187", GetName(oCreature));
|
||||
ai_CopyMonster(oCreature, oModule);
|
||||
// This is a hak to allow wild shaped creatures to be able to attack!
|
||||
if(GetHasFeat(FEAT_WILD_SHAPE, oCreature))
|
||||
{
|
||||
AssignCommand(oCreature, ActionUseFeat(FEAT_WILD_SHAPE, oCreature, SUBFEAT_WILD_SHAPE_BADGER));
|
||||
DelayCommand(4.0, ai_RemoveASpecificEffect(oCreature, EFFECT_TYPE_POLYMORPH));
|
||||
}
|
||||
return;
|
||||
}
|
||||
json ai_SetCompanionSummoning(object oCreature, json jCreature)
|
||||
@@ -198,7 +233,7 @@ json ai_SetCompanionSummoning(object oCreature, json jCreature)
|
||||
jFamiliar = JsonObjectSet(jFamiliar, "value", JsonString("Summoned Familiar"));
|
||||
jCreature = JsonObjectSet(jCreature, "FamiliarName", jFamiliar);
|
||||
jFamiliar = JsonObjectGet(jCreature, "FamiliarType");
|
||||
jFamiliar = JsonObjectSet(jFamiliar, "value", JsonInt(Random(11)));
|
||||
jFamiliar = JsonObjectSet(jFamiliar, "value", JsonInt(10)); //JsonInt(Random(11)));
|
||||
return JsonObjectSet(jCreature, "FamiliarType", jFamiliar);
|
||||
}
|
||||
if(GetHasFeat(FEAT_ANIMAL_COMPANION , oCreature, TRUE))
|
||||
@@ -217,9 +252,9 @@ int ai_ChangeMonster(object oCreature, object oModule)
|
||||
object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oCreature);
|
||||
// Lets not mess up the cutscenes with silly RULES.
|
||||
if(GetCutsceneMode(oPC)) return FALSE;
|
||||
//float fDistance = GetDistanceBetween(oCreature, oPC);
|
||||
float fDistance = GetDistanceBetween(oCreature, oPC);
|
||||
// Looks bad to see creatures wink in and out plus could cause module errors.
|
||||
//if(fDistance != 0.0 && fDistance < AI_RANGE_PERCEPTION) return oCreature;
|
||||
if(fDistance != 0.0 && fDistance < 20.0) return FALSE;
|
||||
if(IsInConversation(oCreature)) return FALSE;
|
||||
json jCreature = ObjectToJson(oCreature, TRUE);
|
||||
// We now use plugins to mod our monsters.
|
||||
@@ -238,8 +273,8 @@ int ai_ChangeMonster(object oCreature, object oModule)
|
||||
jCreature = GetLocalJson(oModule, AI_MONSTER_JSON);
|
||||
}
|
||||
int nSummon = GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS) &&
|
||||
(GetHasFeat(FEAT_SUMMON_FAMILIAR, oCreature, TRUE)) ||
|
||||
GetHasFeat(FEAT_ANIMAL_COMPANION, oCreature, TRUE);
|
||||
(GetHasFeat(FEAT_SUMMON_FAMILIAR, oCreature, TRUE) ||
|
||||
GetHasFeat(FEAT_ANIMAL_COMPANION, oCreature, TRUE));
|
||||
int nPercDist = GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE) != 11 &&
|
||||
GetReputation(oCreature, oPC) < 11;
|
||||
//WriteTimestampedLogEntry(GetName(oCreature) + ": fDistance: " + FloatToString(fDistance, 0, 2) + " nSummon: " + IntToString(nSummon) +
|
||||
@@ -256,10 +291,12 @@ int ai_ChangeMonster(object oCreature, object oModule)
|
||||
if(nSummon) jCreature = ai_SetCompanionSummoning(oCreature, jCreature);
|
||||
SetLocalInt(oModule, AI_MONSTER_CHANGED, TRUE);
|
||||
}
|
||||
// Did any of the Monster mods get used? These are done in independent mod scripts.
|
||||
if(GetLocalInt(oModule, AI_MONSTER_CHANGED))
|
||||
{
|
||||
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);
|
||||
@@ -268,11 +305,18 @@ int ai_ChangeMonster(object oCreature, object oModule)
|
||||
else ai_CopyMonster(oCreature, oModule);
|
||||
DeleteLocalJson(oModule, AI_MONSTER_JSON);
|
||||
DeleteLocalObject(oModule, AI_MONSTER_OBJECT);
|
||||
// This is a hak to allow wild shaped creatures to be able to attack!
|
||||
if(GetHasFeat(FEAT_WILD_SHAPE))
|
||||
{
|
||||
AssignCommand(oCreature, ActionUseFeat(FEAT_WILD_SHAPE, oCreature, SUBFEAT_WILD_SHAPE_BADGER));
|
||||
DelayCommand(4.0, ai_RemoveASpecificEffect(oCreature, EFFECT_TYPE_POLYMORPH));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
// Special event scripts for Infinite Dungeons!
|
||||
void ai_SetIDMonsterEventScripts(object oCreature)
|
||||
{
|
||||
if(GetIsPC(oCreature)) return;
|
||||
//if(AI_DEBUG) ai_Debug("0i_module", "433", "Changing " + GetName(oCreature) + "'s Infinte Dungeons event scripts.");
|
||||
//********** On Heartbeat **********
|
||||
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT);
|
||||
@@ -355,6 +399,7 @@ void ai_SetIDMonsterEventScripts(object oCreature)
|
||||
// Special event scripts for Infinite Dungeons with PRC!
|
||||
void ai_SetPRCIDMonsterEventScripts(object oCreature)
|
||||
{
|
||||
if(GetIsPC(oCreature)) return;
|
||||
//if(AI_DEBUG) ai_Debug("0i_module", "433", "Changing " + GetName(oCreature) + "'s Infinte Dungeons event scripts for PRC.");
|
||||
//********** On Heartbeat **********
|
||||
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT);
|
||||
@@ -437,6 +482,7 @@ void ai_SetPRCIDMonsterEventScripts(object oCreature)
|
||||
// Special event scripts for PRC associates!
|
||||
void ai_SetPRCAssociateEventScripts(object oCreature)
|
||||
{
|
||||
if(GetIsPC(oCreature)) return;
|
||||
//if(AI_DEBUG) ai_Debug("0i_module", "433", "Changing " + GetName(oCreature) + "'s Infinte Dungeons event scripts for PRC.");
|
||||
//********** On Heartbeat **********
|
||||
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT);
|
||||
@@ -494,6 +540,7 @@ void ai_SetPRCAssociateEventScripts(object oCreature)
|
||||
}
|
||||
void ai_ChangeEventScriptsForMonster(object oCreature)
|
||||
{
|
||||
if(GetIsPC(oCreature)) return;
|
||||
//********** On Heartbeat **********
|
||||
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT);
|
||||
if(sScript == "0e_c2_1_hb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "nw_c2_default1");
|
||||
@@ -528,6 +575,7 @@ void ai_ChangeEventScriptsForMonster(object oCreature)
|
||||
}
|
||||
void ai_ChangeEventScriptsForAssociate(object oCreature)
|
||||
{
|
||||
if(GetIsPC(oCreature)) return;
|
||||
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "nw_ch_ac1");
|
||||
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "nw_ch_ac2");
|
||||
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "nw_ch_ac3");
|
||||
|
||||
@@ -8,11 +8,9 @@
|
||||
#include "0i_menus"
|
||||
// Setup an AI OnPlayerTarget Event script while allowing any module onplayer
|
||||
// target event script to still work.
|
||||
void ai_SetupPlayerTarget(object oCreature);
|
||||
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,7 +28,14 @@ void ai_UpdateAssociateWidget(object oPC, object oAssociate);
|
||||
// Sets oAssociates action mode for nFeat from the quick widget menu
|
||||
int ai_SetActionMode(object oAssociate, int nFeat);
|
||||
|
||||
void ai_SetupPlayerTarget(object oCreature)
|
||||
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();
|
||||
string sModuleTargetEvent = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_TARGET);
|
||||
@@ -40,129 +45,7 @@ void ai_SetupPlayerTarget(object oCreature)
|
||||
}
|
||||
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) &&
|
||||
@@ -204,12 +87,14 @@ void ai_ActionAssociate(object oPC, object oTarget, location lLocation)
|
||||
{
|
||||
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, GetLocalString(oAssociate, AI_DEFAULT_SCRIPT));
|
||||
}
|
||||
if(ai_GetIsInCombat(oAssociate)) ai_DoAssociateCombatRound(oAssociate, oTarget);
|
||||
else
|
||||
{
|
||||
ai_HaveCreatureSpeak(oAssociate, 5, ":0:1:2:3:6:");
|
||||
ai_StartAssociateCombat(oAssociate, oTarget);
|
||||
}
|
||||
//if(ai_GetIsInCombat(oAssociate)) ai_DoAssociateCombatRound(oAssociate, oTarget);
|
||||
//else
|
||||
//{
|
||||
// ai_HaveCreatureSpeak(oAssociate, 5, ":0:1:2:3:6:");
|
||||
// ai_StartAssociateCombat(oAssociate, oTarget);
|
||||
//}
|
||||
if(ai_GetIsRangeWeapon(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oAssociate))) ActionAttack(oTarget, TRUE);
|
||||
else ActionAttack(oTarget);
|
||||
ai_SendMessages(GetName(oAssociate) + " is attacking " + GetName(oTarget), AI_COLOR_RED, oPC);
|
||||
}
|
||||
else
|
||||
@@ -231,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;
|
||||
}
|
||||
}
|
||||
@@ -256,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;
|
||||
}
|
||||
|
||||
@@ -289,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)
|
||||
{
|
||||
@@ -298,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)
|
||||
@@ -317,6 +202,7 @@ void ai_SelectFollowTarget(object oPC, object oAssociate, object oTarget)
|
||||
{
|
||||
ai_SetAIMode(oAssociate, AI_MODE_FOLLOW, FALSE);
|
||||
DeleteLocalObject(oAssociate, AI_FOLLOW_TARGET);
|
||||
ClearAllActions(FALSE, oAssociate);
|
||||
string sTarget;
|
||||
if(ai_GetIsCharacter(oAssociate))
|
||||
{
|
||||
@@ -340,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;
|
||||
@@ -634,21 +492,23 @@ void ai_SelectWidgetSpellTarget(object oPC, object oAssociate, string sElem)
|
||||
json jSpell = JsonArrayGet(jWidget, nIndex);
|
||||
int nSpell = JsonGetInt(JsonArrayGet(jSpell, 0));
|
||||
int nClass = JsonGetInt(JsonArrayGet(jSpell, 1));
|
||||
SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate);
|
||||
if(nClass == -1) // This is an Item.
|
||||
{
|
||||
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));
|
||||
@@ -693,8 +553,7 @@ void ai_SelectWidgetSpellTarget(object oPC, object oAssociate, string sElem)
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_ATTACK, MOUSECURSOR_NOATTACK);
|
||||
}
|
||||
// Check feat and adjust if it is an action mode feat.
|
||||
if(ai_SetActionMode(oAssociate, nFeat)) return;
|
||||
AssignCommand(oAssociate, ActionUseFeat(nFeat, oAssociate, nSpell));
|
||||
if(!ai_SetActionMode(oAssociate, nFeat)) AssignCommand(oAssociate, ActionUseFeat(nFeat, oAssociate, nSpell));
|
||||
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
|
||||
return;
|
||||
}
|
||||
@@ -702,7 +561,6 @@ void ai_SelectWidgetSpellTarget(object oPC, object oAssociate, string sElem)
|
||||
}
|
||||
else SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_CAST_SPELL");
|
||||
}
|
||||
SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate);
|
||||
int nObjectType;
|
||||
string sTarget = Get2DAString("spells", "TargetType", nSpell);
|
||||
int nTarget = ai_HexStringToInt(sTarget);
|
||||
@@ -784,6 +642,7 @@ int ai_SetActionMode(object oAssociate, int nFeat)
|
||||
else if(nFeat == FEAT_EXPERTISE) nMode = ACTION_MODE_EXPERTISE;
|
||||
else if(nFeat == FEAT_IMPROVED_EXPERTISE) nMode = ACTION_MODE_IMPROVED_EXPERTISE;
|
||||
else if(nFeat == FEAT_DIRTY_FIGHTING) nMode = ACTION_MODE_DIRTY_FIGHTING;
|
||||
else if(nFeat == FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE) nMode = 12; // ACTION_MODE_DEFENSIVE_STANCE
|
||||
if(nMode)
|
||||
{
|
||||
SetActionMode(oAssociate, nMode, !GetActionMode(oAssociate, nMode));
|
||||
|
||||
@@ -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 #.
|
||||
@@ -163,6 +163,12 @@ void ai_CastBuffs(object oCaster, int nBuffType, int nTarget, object oPC);
|
||||
// Returns TRUE if oCaster cast spontaneous cure spell on oTarget.
|
||||
// This uses an action and must use AssignCommand or OBJECT_SELF is the caster!
|
||||
int ai_CastSpontaneousCure(object oCreature, object oTarget, object oPC);
|
||||
// Returns TRUE if oCaster casts a memorized inflict spell on oTarget.
|
||||
// This uses an action and must use AssignCommand or OBJECT_SELF is the caster!
|
||||
int ai_CastMemorizedInflict(object oCreature, object oTarget, object oPC, int nClass);
|
||||
// Returns TRUE if oCaster casts a known inflict spell on oTarget.
|
||||
// This uses an action and must use AssignCommand or OBJECT_SELF is the caster!
|
||||
int ai_CastKnownInflict(object oCreature, object oTarget, object oPC, int nClass);
|
||||
// Returns TRUE if oCaster casts a memorized cure spell on oTarget.
|
||||
// This uses an action and must use AssignCommand or OBJECT_SELF is the caster!
|
||||
int ai_CastMemorizedHealing(object oCreature, object oTarget, object oPC, int nClass);
|
||||
@@ -178,6 +184,8 @@ void ai_SpellConcentrationCheck(object oCaster);
|
||||
int ai_CastInMelee(object oCreature, int nSpell, int nInMelee);
|
||||
// Returns a float range for the caster to search for a target of an offensive spell.
|
||||
float ai_GetOffensiveSpellSearchRange(object oCreature, int nSpell);
|
||||
// Returns TRUE if nSpell is an inflict spell and will not over heal for nDamage.
|
||||
int ai_ShouldWeCastThisInflictSpell(int nSpell, int nDamage);
|
||||
// Returns TRUE if nSpell is a cure spell and will not over heal for nDamage.
|
||||
int ai_ShouldWeCastThisCureSpell(int nSpell, int nDamage);
|
||||
// Casts the spell on the current target for oAssociate.
|
||||
@@ -394,73 +402,198 @@ int ai_GetIsSpellBookRestrictedCaster(object oAssociate)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
// This is used to set immunities on a creature not using the AI.
|
||||
// Should only update every minute.
|
||||
void ai_SetCreatureItemImmunities(object oCreature)
|
||||
{
|
||||
// Create an Immunity in json so we can check item immunities quickly for non-AI creatures.
|
||||
SetLocalInt(oCreature, sIPTimeStampVarname, ai_GetCurrentTimeStamp());
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "402", "Checking for Item immunities on " + GetName(oCreature));
|
||||
int nSpellImmunity, bHasItemImmunity, nSlot;
|
||||
json jImmunity = JsonArray();
|
||||
DeleteLocalInt(oCreature, sIPImmuneVarname);
|
||||
DeleteLocalInt(oCreature, sIPResistVarname);
|
||||
DeleteLocalInt(oCreature, sIPReducedVarname);
|
||||
int nIprpSubType, nSpell, nLevel, nIPType, nIndex;
|
||||
itemproperty ipProp;
|
||||
// Cycle through all the creatures equiped items.
|
||||
object oItem = GetItemInSlot(nSlot, oCreature);
|
||||
while(nSlot < 12)
|
||||
{
|
||||
if(oItem != OBJECT_INVALID)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "416", "Checking Item immunities on " + GetName(oItem));
|
||||
ipProp = GetFirstItemProperty(oItem);
|
||||
// Check for immunities on items.
|
||||
while(GetIsItemPropertyValid(ipProp))
|
||||
{
|
||||
nIPType = GetItemPropertyType(ipProp);
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "422", "ItempropertyType(53/20/23/22): " + IntToString(nIPType));
|
||||
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_IMMUNITY_DAMAGE_TYPE)
|
||||
{
|
||||
int nBit, nIpSubType = GetItemPropertySubType(ipProp);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "434", "Immune DmgType: 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(AI_DEBUG) ai_Debug("0i_talents", "452", "Dmg Resist: 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, sIPResistVarname, nBit, TRUE);
|
||||
}
|
||||
else if(nIPType == ITEM_PROPERTY_DAMAGE_REDUCTION)
|
||||
{
|
||||
int nIpSubType = GetItemPropertySubType(ipProp);
|
||||
if(AI_DEBUG) ai_Debug("0i_talents", "470", "Dmg Reduction: nIPSubType: " + IntToString(nIpSubType));
|
||||
SetLocalInt(oCreature, sIPReducedVarname, nIpSubType);
|
||||
}
|
||||
nIndex++;
|
||||
ipProp = GetNextItemProperty(oItem);
|
||||
}
|
||||
// If nSpellImmunity has been set then we need to save our Immunity json.
|
||||
if(bHasItemImmunity) SetLocalJson(oCreature, AI_TALENT_IMMUNITY, jImmunity);
|
||||
}
|
||||
oItem = GetItemInSlot(++nSlot, oCreature);
|
||||
// Make the final check the creatures hide.
|
||||
if(nSlot == 11) oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oCreature);
|
||||
}
|
||||
}
|
||||
int ai_CreatureImmuneToEffect(object oCaster, object oCreature, int nSpell)
|
||||
{
|
||||
// This checks for creatures not using the AI system (usually players).
|
||||
// Creatures using the AI system will always have a value in sIPReducedVarname!
|
||||
// Updates thier immunity values every minute. Should be good as we only update
|
||||
// equiped items. Spell effects are checked on the creature and are not saved.
|
||||
if(AI_DEBUG)
|
||||
{
|
||||
if(GetLocalInt(oCreature, sIPReducedVarname) == 0) ai_Debug("0i_spells", "492",
|
||||
" Immunities last saved: " + IntToString(GetLocalInt(oCreature, sIPTimeStampVarname)) +
|
||||
" + 60 < " + IntToString(ai_GetCurrentTimeStamp()));
|
||||
}
|
||||
if(GetLocalInt(oCreature, sIPReducedVarname) == 0 &&
|
||||
GetLocalInt(oCreature, sIPTimeStampVarname) + 60 < ai_GetCurrentTimeStamp()) ai_SetCreatureItemImmunities(oCreature);
|
||||
string sIType = Get2DAString("ai_spells", "ImmunityType", nSpell);
|
||||
// Let us check if the creature is disabled while we look for immunities.
|
||||
int nDisabled = ai_Disabled(oCreature);
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "499", "Checking spell immunity type(" + sIType + ").");
|
||||
if(sIType != "")
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "290", "Checking spell immunity type(" + sIType + ").");
|
||||
if(sIType == "Death" && GetIsImmune(oCreature, IMMUNITY_TYPE_DEATH)) return TRUE;
|
||||
else if(sIType == "Level_Drain" && GetIsImmune(oCreature, IMMUNITY_TYPE_NEGATIVE_LEVEL)) return TRUE;
|
||||
else if(sIType == "Ability_Drain" && GetIsImmune(oCreature, IMMUNITY_TYPE_ABILITY_DECREASE)) return TRUE;
|
||||
else if(sIType == "Poison" && GetIsImmune(oCreature, IMMUNITY_TYPE_POISON)) return TRUE;
|
||||
else if(sIType == "Disease" && GetIsImmune(oCreature, IMMUNITY_TYPE_DISEASE)) return TRUE;
|
||||
else if(sIType == "Curse" && GetIsImmune(oCreature, IMMUNITY_TYPE_CURSED)) return TRUE;
|
||||
else if(sIType == "Mind_Affecting" && GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS)) return TRUE;
|
||||
else if(sIType == "Petrification" && ai_IsImmuneToPetrification(oCaster, oCreature)) return TRUE;
|
||||
else if(sIType == "Mind_Affecting" &&
|
||||
(GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS) || nDisabled)) return TRUE;
|
||||
else if(sIType == "Petrification" &&
|
||||
(ai_IsImmuneToPetrification(oCaster, oCreature) && nDisabled)) return TRUE;
|
||||
else if(sIType == "Fear" &&
|
||||
(GetIsImmune(oCreature, IMMUNITY_TYPE_FEAR) ||
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE;
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS) || nDisabled)) return TRUE;
|
||||
else if(sIType == "Sleep" &&
|
||||
(GetIsImmune(oCreature, IMMUNITY_TYPE_SLEEP) ||
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE;
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS) || nDisabled)) return TRUE;
|
||||
else if(sIType == "Paralysis" &&
|
||||
(GetIsImmune(oCreature, IMMUNITY_TYPE_PARALYSIS) ||
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE;
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS) || nDisabled)) return TRUE;
|
||||
else if(sIType == "Domination" &&
|
||||
(GetIsImmune(oCreature, IMMUNITY_TYPE_DOMINATE) ||
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE;
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS) || nDisabled)) return TRUE;
|
||||
else if(sIType == "Confusion" &&
|
||||
(GetIsImmune(oCreature, IMMUNITY_TYPE_CONFUSED) ||
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE;
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS) || nDisabled)) return TRUE;
|
||||
else if(sIType == "Blindness" &&
|
||||
(GetIsImmune(oCreature, IMMUNITY_TYPE_BLINDNESS) ||
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE;
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS) || ai_GetHasEffectType(oCreature, EFFECT_TYPE_BLINDNESS))) return TRUE;
|
||||
else if(sIType == "Dazed" &&
|
||||
(GetIsImmune(oCreature, IMMUNITY_TYPE_DAZED) ||
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE;
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS) || nDisabled)) return TRUE;
|
||||
else if(sIType == "Charm" &&
|
||||
(GetIsImmune(oCreature, IMMUNITY_TYPE_CHARM) ||
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS))) return TRUE;
|
||||
GetIsImmune(oCreature, IMMUNITY_TYPE_MIND_SPELLS) || nDisabled)) return TRUE;
|
||||
// Check for damage immunities.
|
||||
// Negative damage does not work on undead!
|
||||
else if(sIType == "Negative" && GetRacialType(oCreature) == RACIAL_TYPE_UNDEAD)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "325", "Undead are immune to Negative energy!");
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "538", "Undead are immune to Negative energy!");
|
||||
return TRUE;
|
||||
}
|
||||
else if(sIType == "Poison" && ai_GetHasEffectType(oCreature, EFFECT_TYPE_POISON)) return TRUE;
|
||||
else if(sIType == "Disease" && ai_GetHasEffectType(oCreature, EFFECT_TYPE_DISEASE)) return TRUE;
|
||||
// Elemental damage resistances should be checked.
|
||||
if(sIType == "Acid" || sIType == "Cold" || sIType == "Fire" ||
|
||||
sIType == "Electricty" || sIType == "Sonic")
|
||||
{
|
||||
if(ai_GetHasEffectType(oCreature, EFFECT_TYPE_DAMAGE_RESISTANCE))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "334", GetName(oCreature) + " has damage resistance to my " + sIType + " spell!");
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "547", GetName(oCreature) + " has damage resistance to my " + sIType + " spell!");
|
||||
return TRUE;
|
||||
}
|
||||
// Check for resistances and immunities. Treat resistance as immune.
|
||||
int nIPResist = GetLocalInt(oCreature, sIPResistVarname);
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "372", "nIPResist:" + IntToString(nIPResist));
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "552", "nIPResist:" + IntToString(nIPResist));
|
||||
int nIPImmune = GetLocalInt(oCreature, sIPImmuneVarname) | nIPResist;
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "374", "nIPImmune:" + IntToString(nIPImmune));
|
||||
if(nIPImmune > 0)
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "554", "nIPImmune:" + IntToString(nIPImmune));
|
||||
int bImmune;
|
||||
if(nIPImmune > 0) {
|
||||
|
||||
if(sIType == "Acid" && (nIPImmune & DAMAGE_TYPE_ACID)) bImmune = TRUE;
|
||||
else if(sIType == "Cold" && (nIPImmune & DAMAGE_TYPE_COLD)) bImmune = TRUE;
|
||||
else if(sIType == "Fire" && (nIPImmune & DAMAGE_TYPE_FIRE)) bImmune = TRUE;
|
||||
else if(sIType == "Electricity" && (nIPImmune & DAMAGE_TYPE_ELECTRICAL)) bImmune = TRUE;
|
||||
else if(sIType == "Sonic" && (nIPImmune & DAMAGE_TYPE_SONIC)) bImmune = TRUE;
|
||||
}
|
||||
if(bImmune)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "391", GetName(oCreature) + " is immune/resistant to my " + sIType + " spell through an item!");
|
||||
if(sIType == "Acid" && (nIPImmune & DAMAGE_TYPE_ACID)) return TRUE;
|
||||
else if(sIType == "Cold" && (nIPImmune & DAMAGE_TYPE_COLD)) return TRUE;
|
||||
else if(sIType == "Fire" && (nIPImmune & DAMAGE_TYPE_FIRE)) return TRUE;
|
||||
else if(sIType == "Electricity" && (nIPImmune & DAMAGE_TYPE_ELECTRICAL)) return TRUE;
|
||||
else if(sIType == "Sonic" && (nIPImmune & DAMAGE_TYPE_SONIC)) return TRUE;
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "567", GetName(oCreature) + " is immune/resistant to my " + sIType + " spell through an item!");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
// Lets also check undead and constructs vs mind spells.
|
||||
int nRace = GetRacialType(oCreature);
|
||||
int nClass = GetClassByPosition(1, oCreature);
|
||||
if(nRace == RACIAL_TYPE_UNDEAD || nRace == RACIAL_TYPE_CONSTRUCT ||
|
||||
nClass == CLASS_TYPE_UNDEAD || nClass == CLASS_TYPE_CONSTRUCT)
|
||||
{
|
||||
if(sIType == "Mind_Affecting" || sIType == "Fear" || sIType == "Sleep" ||
|
||||
sIType == "Confusion" || sIType == "Blindness" || sIType == "Daze" ||
|
||||
sIType == "Poison" || sIType == "Disease" || sIType == "Charm")
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "595", GetName(oCreature) + " is immune/resistant to my " + sIType + " spell because they are Undead or a Construct!");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,12 +612,12 @@ int ai_CreatureImmuneToEffect(object oCaster, object oCreature, int nSpell)
|
||||
{
|
||||
if(nSpell == JsonGetInt(jSpell))
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "407", GetName(oCreature) + " is immune to the spell via an Item!");
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "581", GetName(oCreature) + " is immune to the spell via an Item!");
|
||||
return TRUE;
|
||||
}
|
||||
jSpell = JsonArrayGet(jSpellImmunity, ++nIndex);
|
||||
}
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "347", GetName(oCreature) + " is not immune to the spell.");
|
||||
if(AI_DEBUG) ai_Debug("0i_spell", "586", GetName(oCreature) + " is not immune to the spell.");
|
||||
return FALSE;
|
||||
}
|
||||
float ai_GetSpellRange(int nSpell)
|
||||
@@ -651,9 +784,9 @@ int ai_IsSilenced(object oCreature, int nSpell)
|
||||
}
|
||||
int ai_ArcaneSpellFailureTooHigh(object oCreature, int nClass, int nLevel, int nSlot)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "561", "Arcane Spells: " + Get2DAString("classes", "ASF", nClass) +
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "746", "Arcane Spells: " + Get2DAString("classes", "ASF", nClass) +
|
||||
" Arcane Spell Failure: " + IntToString(GetArcaneSpellFailure(oCreature)) +
|
||||
" AI_ASF_WILL_USE: " + IntToString(AI_ASF_WILL_USE));
|
||||
" > " + IntToString(AI_ASF_WILL_USE) + " skip.");
|
||||
if(Get2DAString("classes", "ASF", nClass) == "1" &&
|
||||
GetArcaneSpellFailure(oCreature) > AI_ASF_WILL_USE)
|
||||
{
|
||||
@@ -1181,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)
|
||||
{
|
||||
@@ -1193,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);
|
||||
@@ -1431,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;
|
||||
@@ -1452,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;
|
||||
}
|
||||
}
|
||||
@@ -1466,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;
|
||||
@@ -1492,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;
|
||||
}
|
||||
}
|
||||
@@ -1529,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;
|
||||
@@ -1564,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;
|
||||
}
|
||||
}
|
||||
@@ -1598,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;
|
||||
@@ -1649,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;
|
||||
}
|
||||
}
|
||||
@@ -1682,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;
|
||||
@@ -1734,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;
|
||||
}
|
||||
}
|
||||
@@ -1764,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);
|
||||
@@ -1786,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)
|
||||
{
|
||||
@@ -1802,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;
|
||||
}
|
||||
}
|
||||
@@ -1817,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)
|
||||
{
|
||||
@@ -1883,6 +2022,98 @@ int ai_CastSpontaneousCure(object oCreature, object oTarget, object oPC)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
int ai_CastMemorizedInflict(object oCreature, object oTarget, object oPC, int nClass)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "1993", GetName(oCreature) + " is looking to cast a memorized inflict spell.");
|
||||
int nDamage = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget);
|
||||
int nSpell, nSlot, nMaxSlots, nLevel = 9;
|
||||
int nClassSave, nSlotSave, nLevelSave = 10;
|
||||
while(nLevel > -1)
|
||||
{
|
||||
nMaxSlots = GetMemorizedSpellCountByLevel(oCreature, nClass, nLevel);
|
||||
nSlot = 0;
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "2001", "nLevel: " + IntToString(nLevel) + " nMaxSlots: " + IntToString(nMaxSlots));
|
||||
while(nSlot < nMaxSlots)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "2004", "nSlot: " + IntToString(nSlot) +
|
||||
" Spell Ready: " + IntToString(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot)));
|
||||
if(GetMemorizedSpellReady(oCreature, nClass, nLevel, nSlot))
|
||||
{
|
||||
nSpell = GetMemorizedSpellId(oCreature, nClass, nLevel, nSlot);
|
||||
if(ai_ShouldWeCastThisInflictSpell(nSpell, nDamage))
|
||||
{
|
||||
string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "2012", GetName(oCreature) + " has cast " + sSpellName + " on " + GetName(oTarget) + ".");
|
||||
ai_CastMemorizedSpell(oCreature, nClass, nLevel, nSlot, oTarget, FALSE, oPC);
|
||||
return TRUE;
|
||||
}
|
||||
// Save the lowest level inflict spell as we might need to cast it.
|
||||
else if(nLevel < nLevelSave && (nSpell > 430 && nSpell < 436))
|
||||
{
|
||||
nClassSave = nClass;
|
||||
nLevelSave = nLevel;
|
||||
nSlotSave = nSlot;
|
||||
}
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
nLevel--;
|
||||
}
|
||||
// Did we find a cure spell? If we did then use it.
|
||||
if(nLevelSave < 10)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "1740", GetName(oCreature) + " has cast the lowest level cure spell on " + GetName(oTarget) + ".");
|
||||
ai_CastMemorizedSpell(oCreature, nClassSave, nLevelSave, nSlotSave, oTarget, FALSE, oPC);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
int ai_CastKnownInflict(object oCreature, object oTarget, object oPC, int nClass)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "2041", GetName(oCreature) + " is looking to cast a known inflict spell.");
|
||||
int nDamage = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget);
|
||||
int nSpell, nSlot, nMaxSlots, nLevel = 9;
|
||||
int nClassSave, nSpellSave, nLevelSave = 10;
|
||||
while(nLevel > -1)
|
||||
{
|
||||
nMaxSlots = GetKnownSpellCount(oCreature, nClass, nLevel);
|
||||
nSlot = 0;
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "2049", "nLevel: " + IntToString(nLevel) + " nMaxSlots: " + IntToString(nMaxSlots));
|
||||
while(nSlot < nMaxSlots)
|
||||
{
|
||||
nSpell = GetKnownSpellId(oCreature, nClass, nLevel, nSlot);
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "2053", "nSlot: " + IntToString(nSlot) +
|
||||
" Spell Ready: " + IntToString(GetSpellUsesLeft(oCreature, nClass, nSpell)));
|
||||
if(GetSpellUsesLeft(oCreature, nClass, nSpell))
|
||||
{
|
||||
if(ai_ShouldWeCastThisInflictSpell(nSpell, nDamage))
|
||||
{
|
||||
string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "2060", GetName(oCreature) + " has cast " + sSpellName + " on " + GetName(oTarget) + ".");
|
||||
ai_CastKnownSpell(oCreature, nClass, nSpell, oTarget, FALSE, oPC);
|
||||
return TRUE;
|
||||
}
|
||||
// Save the lowest level cure spell as we might need to cast it.
|
||||
else if(nLevel < nLevelSave && (nSpell > 430 && nSpell < 436))
|
||||
{
|
||||
nClassSave = nClass;
|
||||
nLevelSave = nLevel;
|
||||
nSpellSave = nSpell;
|
||||
}
|
||||
}
|
||||
nSlot++;
|
||||
}
|
||||
nLevel--;
|
||||
}
|
||||
return FALSE;
|
||||
// Did we find a cure spell? If we did then use it.
|
||||
if(nLevelSave < 10)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "1781", GetName(oCreature) + " has cast the lowest level cure spell on " + GetName(oTarget) + ".");
|
||||
ai_CastKnownSpell(oCreature, nClassSave, nSpellSave, oTarget, FALSE, oPC);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
int ai_CastMemorizedHealing(object oCreature, object oTarget, object oPC, int nClass)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "1702", GetName(oCreature) + " is looking to cast a memorized cure spell.");
|
||||
@@ -1909,7 +2140,7 @@ int ai_CastMemorizedHealing(object oCreature, object oTarget, object oPC, int nC
|
||||
return TRUE;
|
||||
}
|
||||
// Save the lowest level cure spell as we might need to cast it.
|
||||
else if(nLevel < nLevelSave && (nSpell > 26 && nSpell < 32))
|
||||
else if(nLevel < nLevelSave && (nSpell > 30 && nSpell < 36))
|
||||
{
|
||||
nClassSave = nClass;
|
||||
nLevelSave = nLevel;
|
||||
@@ -1955,7 +2186,7 @@ int ai_CastKnownHealing(object oCreature, object oTarget, object oPC, int nClass
|
||||
return TRUE;
|
||||
}
|
||||
// Save the lowest level cure spell as we might need to cast it.
|
||||
else if(nLevel < nLevelSave && (nSpell > 26 && nSpell < 32))
|
||||
else if(nLevel < nLevelSave && (nSpell > 30 && nSpell < 36))
|
||||
{
|
||||
nClassSave = nClass;
|
||||
nLevelSave = nLevel;
|
||||
@@ -2074,7 +2305,7 @@ float ai_GetOffensiveSpellSearchRange(object oCreature, int nSpell)
|
||||
// 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!
|
||||
int nAction = GetCurrentAction(oNearestEnemy);
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "1130", GetName(oNearestEnemy) + " current action: " + IntToString(nAction));
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "2228", GetName(oNearestEnemy) + " current action: " + IntToString(nAction));
|
||||
if(nAction != ACTION_MOVETOPOINT || nAction != ACTION_ITEMCASTSPELL ||
|
||||
nAction != ACTION_INVALID || nAction != ACTION_USEOBJECT ||
|
||||
nAction != ACTION_RANDOMWALK) fRange = fEnemyDistance + (fRange - 7.5);
|
||||
@@ -2083,6 +2314,18 @@ float ai_GetOffensiveSpellSearchRange(object oCreature, int nSpell)
|
||||
else if(fRange < 0.1f) return 0.1f;
|
||||
return fRange;
|
||||
}
|
||||
int ai_ShouldWeCastThisInflictSpell(int nSpell, int nDamage)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "2239", "nSpell: " + IntToString(nSpell) + " nDamage: " +
|
||||
IntToString(nDamage));
|
||||
if(nSpell == SPELL_HEAL && nDamage > 50) return TRUE;
|
||||
else if(nSpell == SPELL_INFLICT_CRITICAL_WOUNDS && nDamage > 31) return TRUE;
|
||||
else if(nSpell == SPELL_INFLICT_SERIOUS_WOUNDS && nDamage > 23) return TRUE;
|
||||
else if(nSpell == SPELL_INFLICT_MODERATE_WOUNDS && nDamage > 15) return TRUE;
|
||||
else if(nSpell == SPELL_INFLICT_LIGHT_WOUNDS && nDamage > 6) return TRUE;
|
||||
else if(nSpell == SPELL_INFLICT_MINOR_WOUNDS) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
int ai_ShouldWeCastThisCureSpell(int nSpell, int nDamage)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_spells", "1127", "nSpell: " + IntToString(nSpell) + " nDamage: " +
|
||||
@@ -2112,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));
|
||||
@@ -2134,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))
|
||||
{
|
||||
@@ -2155,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);
|
||||
@@ -2172,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)
|
||||
{
|
||||
@@ -105,6 +106,7 @@ int ai_CompareLastAction(object oCreature, int nAction)
|
||||
}
|
||||
void ai_SetListeningPatterns(object oCreature)
|
||||
{
|
||||
SetListening(oCreature, TRUE);
|
||||
SetListenPattern(oCreature, AI_I_SEE_AN_ENEMY, AI_ALLY_SEES_AN_ENEMY);
|
||||
SetListenPattern(oCreature, AI_I_HEARD_AN_ENEMY, AI_ALLY_HEARD_AN_ENEMY);
|
||||
SetListenPattern(oCreature, AI_ATKED_BY_WEAPON, AI_ALLY_ATKED_BY_WEAPON);
|
||||
@@ -114,7 +116,6 @@ void ai_SetListeningPatterns(object oCreature)
|
||||
SetListenPattern(oCreature, AI_I_AM_DISEASED, AI_ALLY_IS_DISEASED);
|
||||
SetListenPattern(oCreature, AI_I_AM_POISONED, AI_ALLY_IS_POISONED);
|
||||
SetListenPattern(oCreature, AI_I_AM_WEAK, AI_ALLY_IS_WEAK);
|
||||
SetListening(oCreature, TRUE);
|
||||
}
|
||||
int ai_IsNonliving(int nRacialType)
|
||||
{
|
||||
@@ -134,12 +135,12 @@ int ai_GetIsInCombat(object oCreature)
|
||||
}
|
||||
void ai_SetCombatRound(object oCreature)
|
||||
{
|
||||
SetLocalInt(oCreature, "AI_COMBAT_ROUND_START", SQLite_GetTimeStamp());
|
||||
if(AI_DEBUG) ai_Debug("0i_states_cond", "116", " ===============> " + GetName(oCreature) + " ROUND START:" + IntToString(SQLite_GetTimeStamp()) + " <===============");
|
||||
SetLocalInt(oCreature, "AI_COMBAT_ROUND_START", ai_GetCurrentTimeStamp());
|
||||
if(AI_DEBUG) ai_Debug("0i_states_cond", "116", " ===============> " + GetName(oCreature) + " ROUND START:" + IntToString(ai_GetCurrentTimeStamp()) + " <===============");
|
||||
}
|
||||
void ai_EndCombatRound(object oCreature)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("0i_states_cond", "120", " ===============> " + GetName(oCreature) + " ROUND END:" + IntToString(SQLite_GetTimeStamp()) + " <===============");
|
||||
if(AI_DEBUG) ai_Debug("0i_states_cond", "120", " ===============> " + GetName(oCreature) + " ROUND END:" + IntToString(ai_GetCurrentTimeStamp()) + " <===============");
|
||||
DeleteLocalInt(oCreature, "AI_COMBAT_ROUND_START");
|
||||
}
|
||||
int ai_IsInCombatRound(object oCreature, int nCombatRound = AI_COMBAT_ROUND_IN_SECONDS)
|
||||
@@ -148,10 +149,10 @@ int ai_IsInCombatRound(object oCreature, int nCombatRound = AI_COMBAT_ROUND_IN_S
|
||||
if(AI_DEBUG) ai_Debug("0i_states_cond", "148", " nCombatRoundStart: " + IntToString(nCombatRoundStart));
|
||||
if(!nCombatRoundStart) return FALSE;
|
||||
// New combat round calculator. If 6 seconds has passed then we are on a new round!
|
||||
int nSQLTime = SQLite_GetTimeStamp();
|
||||
int nCombatRoundTime = nSQLTime - nCombatRoundStart;
|
||||
if(AI_DEBUG) ai_Debug("0i_states_cond", "153", " SQLite_GetTimeStamp: " + IntToString(nSQLTime) +
|
||||
"(" + IntToString(nSQLTime - nCombatRoundStart) + ")");
|
||||
int nTime = ai_GetCurrentTimeStamp();
|
||||
int nCombatRoundTime = nTime - nCombatRoundStart;
|
||||
if(AI_DEBUG) ai_Debug("0i_states_cond", "153", " nTime + (nTime - Round Start): " + IntToString(nTime) +
|
||||
"(" + IntToString(nTime - nCombatRoundStart) + ")");
|
||||
if(nCombatRoundTime < nCombatRound) return TRUE;
|
||||
ai_EndCombatRound(oCreature);
|
||||
return FALSE;
|
||||
@@ -200,9 +201,11 @@ int ai_Disabled(object oCreature)
|
||||
effect eEffect = GetFirstEffect(oCreature);
|
||||
while(GetIsEffectValid(eEffect))
|
||||
{
|
||||
switch(GetEffectType(eEffect))
|
||||
switch(GetEffectType(eEffect, TRUE))
|
||||
{
|
||||
WriteTimestampedLogEntry("Effect Type: " + IntToString(GetEffectType(eEffect, TRUE)));
|
||||
case EFFECT_TYPE_DOMINATED :
|
||||
case EFFECT_TYPE_CUTSCENE_DOMINATED :
|
||||
{
|
||||
if(!GetCommandable(oCreature)) SetCommandable(TRUE, oCreature);
|
||||
return FALSE;
|
||||
@@ -213,6 +216,7 @@ int ai_Disabled(object oCreature)
|
||||
case EFFECT_TYPE_CONFUSED :
|
||||
case EFFECT_TYPE_FRIGHTENED :
|
||||
case EFFECT_TYPE_PARALYZE :
|
||||
case EFFECT_TYPE_CUTSCENE_PARALYZE :
|
||||
case EFFECT_TYPE_TURNED :
|
||||
case EFFECT_TYPE_CHARMED :
|
||||
case EFFECT_TYPE_PETRIFY :
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,55 +8,42 @@ int GetPosixTimestamp();
|
||||
string GetCurrentDateTime();
|
||||
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
// RETURNS a Timestamp in seconds since 1970-01-01.
|
||||
int GetCurrentTimeInSeconds();
|
||||
// RETURNS a formated date, good for timestamping logs and text.
|
||||
// Returns a Timestamp in seconds since 1970-01-01.
|
||||
int ai_GetCurrentTimeStamp();
|
||||
// Returns a formated date, good for Dating logs and text.
|
||||
string GetCurrentDateTime();
|
||||
// Sends a server shutdown message 1800 seconds i.e 30 minutes before.
|
||||
// nDuration is in seconds. i.e. one hours is 3600 defaults to 24 hours (86400).
|
||||
// Should be put into the servers OnHeartBeat.
|
||||
void CheckServerShutdownMessage(int nDuration = 86400);
|
||||
/// Returns the current time formatted according to the provided sqlite date time format string.
|
||||
/// Format string as used by sqlites STRFTIME().
|
||||
/// Returns the current time in the requested format. Empty string on error.
|
||||
string SQLite_GetFormattedSystemTime(string format);
|
||||
/// Returns the number of milliseconds since midnight on January 1, 1970.
|
||||
int SQLite_GetTimeMilliseconds();
|
||||
/// Returns the date in the format (mm/dd/yyyy).
|
||||
string SQLite_GetSystemDate();
|
||||
/// Returns the current time in the format (24:mm:ss).
|
||||
string SQLite_GetSystemTime();
|
||||
|
||||
int GetCurrentTimeInSeconds()
|
||||
int ai_GetCurrentTimeStamp()
|
||||
{
|
||||
string stmt = "SELECT strftime('%s','now');";
|
||||
sqlquery sqlQuery = SqlPrepareQueryObject(GetModule(), stmt);
|
||||
SqlStep(sqlQuery);
|
||||
return SqlGetInt(sqlQuery, 0);
|
||||
sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME('%s', 'now')");
|
||||
SqlStep(query);
|
||||
return SqlGetInt(query, 0);
|
||||
}
|
||||
string GetCurrentDateTime()
|
||||
{
|
||||
string stmt = "SELECT datetime('now', 'localtime')";
|
||||
sqlquery sqlQuery = SqlPrepareQueryObject(GetModule(), stmt);
|
||||
sqlquery sqlQuery = SqlPrepareQueryObject(GetModule(), "SELECT datetime('now', 'localtime')");
|
||||
SqlStep(sqlQuery);
|
||||
return SqlGetString(sqlQuery, 0);
|
||||
}
|
||||
/// @addtogroup time Time
|
||||
/// @brief Provides various time related functions.
|
||||
/// @brief Returns the current time formatted according to the provided sqlite date time format string.
|
||||
/// @param format Format string as used by sqlites STRFTIME().
|
||||
/// @return The current time in the requested format. Empty string on error.
|
||||
string SQLite_GetFormattedSystemTime(string format);
|
||||
/// @return Returns the number of seconds since midnight on January 1, 1970.
|
||||
int SQLite_GetTimeStamp();
|
||||
/// @return Returns the number of milliseconds since midnight on January 1, 1970.
|
||||
int SQLite_GetTimeMilliseconds();
|
||||
/// @brief A millisecond timestamp
|
||||
struct SQLite_MillisecondTimeStamp
|
||||
{
|
||||
int seconds; ///< Seconds since epoch
|
||||
int milliseconds; ///< Milliseconds
|
||||
};
|
||||
/// @remark For mircosecond timestamps use NWNX_Utility_GetHighResTimeStamp().
|
||||
/// @return Returns the number of milliseconds since midnight on January 1, 1970.
|
||||
struct SQLite_MillisecondTimeStamp SQLite_GetMillisecondTimeStamp();
|
||||
/// @brief Returns the current date.
|
||||
/// @return The date in the format (mm/dd/yyyy).
|
||||
string SQLite_GetSystemDate();
|
||||
/// @brief Returns current time.
|
||||
/// @return The current time in the format (24:mm:ss).
|
||||
string SQLite_GetSystemTime();
|
||||
/// @}
|
||||
string SQLite_GetFormattedSystemTime(string format)
|
||||
{
|
||||
sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME(@format, 'now', 'localtime')");
|
||||
@@ -64,27 +51,12 @@ string SQLite_GetFormattedSystemTime(string format)
|
||||
SqlStep(query); // sqlite returns NULL for invalid format in STRFTIME()
|
||||
return SqlGetString(query, 0);
|
||||
}
|
||||
int SQLite_GetTimeStamp()
|
||||
{
|
||||
sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME('%s', 'now')");
|
||||
SqlStep(query);
|
||||
return SqlGetInt(query, 0);
|
||||
}
|
||||
int SQLite_GetTimeMillisecond()
|
||||
{
|
||||
sqlquery query = SqlPrepareQueryObject(GetModule(), "select cast((julianday('now') - 2440587.5) * 86400 * 1000 as integer)");
|
||||
SqlStep(query);
|
||||
return SqlGetInt(query, 0);
|
||||
}
|
||||
struct SQLite_MillisecondTimeStamp SQLite_GetMillisecondTimeStamp()
|
||||
{
|
||||
sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME('%s', 'now'), SUBSTR(STRFTIME('%f', 'now'), 4)");
|
||||
SqlStep(query);
|
||||
struct SQLite_MillisecondTimeStamp t;
|
||||
t.seconds = SqlGetInt(query, 0);
|
||||
t.milliseconds = SqlGetInt(query, 1);
|
||||
return t;
|
||||
}
|
||||
string SQLite_GetSystemDate()
|
||||
{
|
||||
return SQLite_GetFormattedSystemTime("%m/%d/%Y");
|
||||
|
||||
@@ -92,18 +92,18 @@ void main()
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
@@ -133,7 +133,7 @@ void main()
|
||||
{
|
||||
oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
|
||||
// If we didn't get a target then get any target within range.
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
|
||||
}
|
||||
// If not then lets go find someone to attack!
|
||||
else
|
||||
@@ -141,7 +141,7 @@ void main()
|
||||
// Get the nearest enemy.
|
||||
oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
|
||||
// If we didn't get a target then get any target within range.
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,18 +92,18 @@ void main()
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
@@ -133,7 +133,7 @@ void main()
|
||||
{
|
||||
oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
|
||||
// If we didn't get a target then get any target within range.
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
|
||||
}
|
||||
// If not then lets go find someone to attack!
|
||||
else
|
||||
@@ -141,7 +141,7 @@ void main()
|
||||
// Get the nearest enemy.
|
||||
oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
|
||||
// If we didn't get a target then get any target within range.
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,12 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,12 +52,12 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -72,12 +72,12 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ void main()
|
||||
if(ai_TryImprovedExpertiseFeat(oCreature)) return;
|
||||
if(ai_TryExpertiseFeat(oCreature)) return;
|
||||
// Lets get the strongest melee opponent in melee with us.
|
||||
oTarget = ai_GetHighestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
oTarget = ai_GetHighestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = oNearestEnemy;
|
||||
// Use knockdown when appropriate and the target is not immune.
|
||||
if(ai_TryKnockdownFeat(oCreature, oTarget)) return;
|
||||
|
||||
@@ -24,12 +24,38 @@ void main()
|
||||
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
|
||||
}
|
||||
// Skill, Class, Offensive AOE's, and Defensive talents.
|
||||
object oTarget = OBJECT_INVALID;
|
||||
// Get the Spell Level we should still cast before turning into our polymorph form.
|
||||
int nSpellLevel = ai_GetHasPolymorphSelfFeat(oCreature);
|
||||
int nMaxTalentLevel;
|
||||
if(AI_DEBUG) ai_Debug("ai_a_druid", "31", "nSpellLevel: " + IntToString(nSpellLevel));
|
||||
if(nDifficulty >= AI_COMBAT_MODERATE)
|
||||
{
|
||||
// *************************** SPELL TALENTS ***************************
|
||||
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
|
||||
{
|
||||
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
|
||||
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
|
||||
}
|
||||
// ************************** CLASS FEATURES ***************************
|
||||
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
|
||||
// *************************** SPELL TALENTS ***************************
|
||||
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
|
||||
//************************** DEFENSIVE TALENTS ***************************
|
||||
if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING))
|
||||
{
|
||||
if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
|
||||
nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_SUMMON);
|
||||
if(AI_DEBUG) ai_Debug("ai_a_druid", "47", "nMaxTalentLevel 'S' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_SUMMON, nInMelee, nMaxLevel, oTarget)) return;
|
||||
nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_PROTECTION);
|
||||
if(AI_DEBUG) ai_Debug("ai_a_druid", "51", "nMaxTalentLevel 'P' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_PROTECTION, nInMelee, nMaxLevel, oTarget)) return;
|
||||
nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_ENHANCEMENT);
|
||||
if(AI_DEBUG) ai_Debug("ai_a_druid", "55", "nMaxTalentLevel 'E' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_ENHANCEMENT, nInMelee, nMaxLevel, oTarget)) return;
|
||||
}
|
||||
}
|
||||
// Offensive single target talents.
|
||||
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
|
||||
@@ -37,16 +63,24 @@ void main()
|
||||
// *************************** SPELL TALENTS ***************************
|
||||
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
|
||||
{
|
||||
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
|
||||
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
|
||||
if(nInMelee > 0)
|
||||
{
|
||||
nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_TOUCH);
|
||||
if(AI_DEBUG) ai_Debug("ai_druid", "69", "nMaxTalentLevel 'T' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
|
||||
}
|
||||
nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_RANGED);
|
||||
if(AI_DEBUG) ai_Debug("ai_druid", "74", "nMaxTalentLevel 'R' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
|
||||
}
|
||||
if(nDifficulty >= AI_COMBAT_MODERATE && ai_TryPolymorphSelfFeat(oCreature)) return;
|
||||
}
|
||||
if(nDifficulty >= AI_COMBAT_MODERATE && ai_TryPolymorphSelfFeat(oCreature)) return;
|
||||
//************************** SKILL FEATURES **************************
|
||||
if(ai_TryAnimalEmpathy(oCreature)) return;
|
||||
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
|
||||
// ************************** Ranged feat attacks **************************
|
||||
object oTarget;
|
||||
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
@@ -56,12 +90,12 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,12 +51,12 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ void main()
|
||||
{
|
||||
oTarget = ai_GetFlankTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
// Ok we are in a serious fight so lets not give attack of opportunities.
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
// Ok we are in a serious fight so lets not give attacks of opportunities.
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
// If there are no enemies being attacked then lets stay back.
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
@@ -83,10 +83,10 @@ void main()
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
|
||||
oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
@@ -98,6 +98,12 @@ void main()
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Make sure we are not the only one here. Moving around looks funny when we are by ourselves.
|
||||
else if(ai_GetNearestAlly(oCreature, 1, 7, 7) == OBJECT_INVALID)
|
||||
{
|
||||
oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
}
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
|
||||
@@ -75,12 +75,12 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,12 +52,12 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -91,17 +91,17 @@ void main()
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
if(AI_DEBUG) ai_Debug("ai_a_no_modes", "105", GetName(OBJECT_SELF) + " does ranged attack on weakest: " + GetName(oTarget) + "!");
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
|
||||
@@ -73,12 +73,12 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Paladins face off against the strongest opponents first.
|
||||
if(!nInMelee) oTarget = ai_GetHighestCRTarget(oCreature);
|
||||
else oTarget = ai_GetHighestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetHighestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetHighestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,21 @@
|
||||
// Programmer: Philos
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_actions"
|
||||
void ai_DoActions(object oCreature, int nForm)
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
|
||||
object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST);
|
||||
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
|
||||
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
|
||||
if(GetPercentageHPLoss(oCreature) <= AI_HEALTH_BLOODY)
|
||||
{
|
||||
//ai_Debug("ai_a_polymorphed", "24", "We are wounded and are transforming back!");
|
||||
if(AI_DEBUG) ai_Debug("ai_a_polymorphed", "20", "We are wounded and are transforming back!");
|
||||
ai_RemoveASpecificEffect(oCreature, EFFECT_TYPE_POLYMORPH);
|
||||
DeleteLocalInt(oCreature, AI_POLYMORPHED);
|
||||
// We need to create the creatures normal forms talent list.
|
||||
DelayCommand(0.0, ai_ClearTalents(oCreature));
|
||||
DelayCommand(0.1, ai_SetCreatureTalents(oCreature, FALSE, TRUE));
|
||||
return;
|
||||
}
|
||||
int nDifficulty = ai_GetDifficulty(oCreature);
|
||||
@@ -51,20 +56,3 @@ void ai_DoActions(object oCreature, int nForm)
|
||||
if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
else ai_SearchForHiddenCreature(oCreature, FALSE);
|
||||
}
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
// Need to know who we are so we can use thier abilities.
|
||||
int nForm = GetAppearanceType(oCreature);
|
||||
// Check to see if we are back to our normal form?(-1 to get the actual form #)
|
||||
if(nForm == GetLocalInt(oCreature, AI_NORMAL_FORM) - 1)
|
||||
{
|
||||
// If we are transformed back then go back to our primary ai.
|
||||
ai_SetCreatureAIScript(oCreature);
|
||||
DeleteLocalInt(oCreature, AI_NORMAL_FORM);
|
||||
string sAI = GetLocalString(oCreature, AI_COMBAT_SCRIPT);
|
||||
if(sAI == "ai_a_polymorphed" || sAI == "") sAI = "ai_a_default";
|
||||
ExecuteScript(sAI, oCreature);
|
||||
}
|
||||
else ai_DoActions(oCreature, nForm);
|
||||
}
|
||||
|
||||
@@ -68,17 +68,17 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget == ai_GetRangedTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID && ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -59,17 +59,17 @@ void main()
|
||||
if(!nInMelee)
|
||||
{
|
||||
oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,12 +52,12 @@ void main()
|
||||
{
|
||||
if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
|
||||
@@ -52,8 +52,8 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
{
|
||||
// Lets pick off the weakest targets.
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
|
||||
@@ -41,11 +41,11 @@ void main()
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,11 +39,11 @@ void main()
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
38
_module/nss/ai_bloodmane.nss
Normal file
38
_module/nss/ai_bloodmane.nss
Normal file
@@ -0,0 +1,38 @@
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Script Name: ai_bloodmane
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
AI combat action scripts for Bloodmane - Orc Warlord(Barbarian - Example).
|
||||
To use this AI set the variable string "AI_DEFAULT_SCRIPT" to "ai_bloodmane" on the creature.
|
||||
*/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Programmer: Philos
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_actions"
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
//**************************************************************************
|
||||
//************************ START SPECIAL AI SCRIPTS ************************
|
||||
//**************************************************************************
|
||||
int nRound = ai_GetCurrentRound(oCreature);
|
||||
// First round cuss and animate!
|
||||
if(nRound == 1)
|
||||
{
|
||||
// Make him taunt the player!
|
||||
ActionPlayAnimation(ANIMATION_FIREFORGET_TAUNT);
|
||||
PlayVoiceChat(Random(4), oCreature);
|
||||
}
|
||||
// Second round go into a Rage.
|
||||
else if(nRound == 2)
|
||||
{
|
||||
// Use Rage!
|
||||
if(ai_TryBarbarianRageFeat(oCreature)) return;
|
||||
// If for some reason he doesn't have a rage then charge into melee!
|
||||
object oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, ai_GetNumOfEnemiesInRange(oCreature));
|
||||
if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
// Change Bloodmane's ai to Barbarian since we are done with his special ai.
|
||||
SetLocalString(oCreature, AI_COMBAT_SCRIPT, "ai_barbarian");
|
||||
}
|
||||
//**************************************************************************
|
||||
//************************ END SPECIAL AI SCRIPTS **************************
|
||||
//**************************************************************************
|
||||
}
|
||||
@@ -41,8 +41,8 @@ void main()
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
|
||||
103
_module/nss/ai_dragon_boss.nss
Normal file
103
_module/nss/ai_dragon_boss.nss
Normal file
@@ -0,0 +1,103 @@
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Script Name: ai_dragon_boss
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ai script a unique dragon that lives deep in a dark cave using it as a defense.
|
||||
OBJECT_SELF is the dragon running the ai.
|
||||
*/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Programmer: Philos
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_actions"
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
// Get the number of enemies that we are in melee combat with.
|
||||
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
|
||||
//**************************************************************************
|
||||
//************************ ROUND BASED AI SCRIPTS *************************
|
||||
//**************************************************************************
|
||||
int nRound = ai_GetCurrentRound(oCreature);
|
||||
// First time fly to our enemy, the rest of combat lets not do that!
|
||||
object oTarget;
|
||||
if(!GetLocalInt(OBJECT_SELF, "AI_DONE_FLYING"))
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, "AI_DONE_FLYING", TRUE);
|
||||
oTarget = ai_GetLowestCRTarget(oCreature);
|
||||
// We assign the voice to the PC so they get to hear it.
|
||||
object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
|
||||
AssignCommand(oPC, PlaySound("vs_ndredm_bat2"));
|
||||
// Can we do a crush attack(HD 18+)?
|
||||
if(ai_TryCrushAttack(oCreature, oTarget)) return;
|
||||
ai_FlyToTarget(oCreature, oTarget);
|
||||
return;
|
||||
}
|
||||
else if(nRound == 2)
|
||||
{
|
||||
oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_CLOSE);
|
||||
ai_TryDragonBreathAttack(oCreature, nRound, oTarget);
|
||||
return;
|
||||
}
|
||||
//*************************** HEALING & CURES ****************************
|
||||
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
|
||||
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
|
||||
// Check to see if we need to retreat to get healing.
|
||||
int nPercentageHP = ai_GetPercHPLoss(oCreature);
|
||||
//ai_Debug("ai_dragon_boss", "43", "nPercentageHP: " + IntToString(nPercentageHP));
|
||||
if(nPercentageHP < 75 && !GetLocalInt(oCreature, "AI_HOME"))
|
||||
{
|
||||
string sWaypoint;
|
||||
// If we are below half then go to last defensive position.
|
||||
if(nPercentageHP < 50)
|
||||
{
|
||||
SetLocalInt(oCreature, "AI_HOME", TRUE);
|
||||
sWaypoint = "0_wp_dragon2";
|
||||
}
|
||||
// else we just go back a little bit to heal up.
|
||||
else sWaypoint = "0_wp_dragon1";
|
||||
if(!GetLocalInt(oCreature, sWaypoint))
|
||||
{
|
||||
string sVoice;
|
||||
switch(d6())
|
||||
{
|
||||
case 1 :
|
||||
case 2 : sVoice = "vs_ndredm_attk"; break;
|
||||
case 3 :sVoice = "vs_ndredm_heal"; break;
|
||||
case 4 :sVoice = "vs_ndredm_help"; break;
|
||||
case 5 :sVoice = "vs_ndredm_no"; break;
|
||||
case 6 :sVoice = "vs_ndredm_bat3"; break;
|
||||
}
|
||||
SetImmortal(oCreature, TRUE);
|
||||
DelayCommand(6.0f, SetImmortal(oCreature, FALSE));
|
||||
AssignCommand(ai_GetNearestTarget(oCreature), PlaySound(sVoice));
|
||||
object oWaypoint = GetNearestObjectByTag(sWaypoint);
|
||||
//ai_Debug("ai_dragon_boss", "71", "Flying to " + sWaypoint + ".");
|
||||
effect eFly = EffectDisappearAppear(GetLocation(oWaypoint));
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFly, oCreature, 6.0f);
|
||||
SetLocalInt(oCreature, sWaypoint, TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature);
|
||||
//******************* OFFENSIVE AREA OF EFFECT TALENTS *******************
|
||||
// Check the battlefield for a group of enemies to shoot a big talent at!
|
||||
// We are checking here since these opportunities are rare and we need
|
||||
// to take advantage of them as often as possible.
|
||||
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
|
||||
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
|
||||
//************************** DEFENSIVE TALENTS ***************************
|
||||
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return;
|
||||
//********************** OFFENSIVE TARGETED TALENTS **********************
|
||||
// Look for a touch attack since we are in melee.
|
||||
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
|
||||
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
|
||||
// ************************ MELEE ATTACKS ********************************
|
||||
oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryDragonBreathAttack(oCreature, nRound)) return;
|
||||
ai_TryWingAttacks(oCreature);
|
||||
// If we don't do a Tail sweep attack(HD 30+) then see if we can do a Tail slap(HD 12+)!
|
||||
if(!ai_TryTailSweepAttack(oCreature)) ai_TryTailSlap(oCreature);
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
}
|
||||
else ai_SearchForHiddenCreature(oCreature, TRUE);
|
||||
}
|
||||
@@ -24,14 +24,36 @@ void main()
|
||||
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
|
||||
//**************************** CLASS FEATURES ****************************
|
||||
if(GetLocalInt(GetModule(), AI_RULE_SUMMON_COMPANIONS) && ai_TrySummonAnimalCompanionTalent(oCreature)) return;
|
||||
if(ai_TryPolymorphSelfFeat(oCreature)) return;
|
||||
//************************** DEFENSIVE TALENTS ***************************
|
||||
int nRound = ai_GetCurrentRound(oCreature);
|
||||
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return;
|
||||
// Get the Spell Level we should still cast before turning into our polymorph form.
|
||||
int nSpellLevel = ai_GetHasPolymorphSelfFeat(oCreature);
|
||||
if(AI_DEBUG) ai_Debug("ai_druid", "30", "nSpellLevel: " + IntToString(nSpellLevel));
|
||||
int nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_SUMMON);
|
||||
if(AI_DEBUG) ai_Debug("ai_druid", "32", "nMaxTalentLevel 'S' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_SUMMON, nInMelee, nMaxLevel)) return;
|
||||
nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_PROTECTION);
|
||||
if(AI_DEBUG) ai_Debug("ai_druid", "36", "nMaxTalentLevel 'P' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_PROTECTION, nInMelee, nMaxLevel)) return;
|
||||
nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_ENHANCEMENT);
|
||||
if(AI_DEBUG) ai_Debug("ai_druid", "40", "nMaxTalentLevel 'E' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_ENHANCEMENT, nInMelee, nMaxLevel)) return;
|
||||
//********************** OFFENSIVE TARGETED TALENTS **********************
|
||||
// Look for a touch attack since we are in melee.
|
||||
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
|
||||
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
|
||||
if(nInMelee > 0)
|
||||
{
|
||||
nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_TOUCH);
|
||||
if(AI_DEBUG) ai_Debug("ai_druid", "48", "nMaxTalentLevel 'T' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
|
||||
}
|
||||
nMaxTalentLevel = GetLocalInt(oCreature, AI_MAX_TALENT + AI_TALENT_RANGED);
|
||||
if(AI_DEBUG) ai_Debug("ai_druid", "53", "nMaxTalentLevel 'R' " + IntToString(nMaxTalentLevel));
|
||||
if(nSpellLevel < nMaxTalentLevel &&
|
||||
ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
|
||||
if(ai_TryPolymorphSelfFeat(oCreature)) return;
|
||||
//**************************** SKILL FEATURES ****************************
|
||||
if(ai_TryAnimalEmpathy(oCreature)) return;
|
||||
// All else fails lets see if we have any good potions.
|
||||
@@ -43,10 +65,11 @@ void main()
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
// Lets pick off the nearest targets.
|
||||
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@ void main()
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ void main()
|
||||
}
|
||||
// **************************** MELEE ATTACKS ****************************
|
||||
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
|
||||
if(ai_TryWhirlwindFeat (oCreature)) return;
|
||||
if(ai_TryWhirlwindFeat(oCreature)) return;
|
||||
oTarget = ai_GetNearestTargetForMeleeCombat (oCreature, nInMelee);
|
||||
if (oTarget != OBJECT_INVALID)
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ void main()
|
||||
oTarget = ai_GetFlankTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
// Ok we are in a serious fight so lets not give attack of opportunities.
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
// If there are no enemies being attacked then lets stay back.
|
||||
if(oTarget == OBJECT_INVALID)
|
||||
@@ -75,10 +75,10 @@ void main()
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
|
||||
oTarget = ai_GetNearestTarget(oCreature);
|
||||
oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ void main()
|
||||
{
|
||||
if (ai_TryRangedSneakAttack (oCreature, nInMelee)) return;
|
||||
string sIndex;
|
||||
if (!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget (oCreature, AI_RANGE_MELEE);
|
||||
if (!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget (oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat (oCreature, oTarget, nInMelee)) return;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ void main()
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ void main()
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if (!nInMelee) oTarget = ai_GetNearestTarget (oCreature);
|
||||
else oTarget = ai_GetNearestTarget (oCreature, AI_RANGE_MELEE);
|
||||
if (!nInMelee) oTarget = ai_GetNearestPhysicalTarget (oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget (oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
|
||||
@@ -43,8 +43,8 @@ void main()
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
// Paladins face the biggest challenges first!
|
||||
if(!nInMelee) oTarget = ai_GetHighestCRTarget(oCreature);
|
||||
else oTarget = ai_GetHighestCRTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetHighestCRPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetHighestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
|
||||
@@ -8,16 +8,21 @@
|
||||
// Programmer: Philos
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_actions"
|
||||
void ai_DoActions(object oCreature, int nForm)
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
|
||||
object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST);
|
||||
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
|
||||
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
|
||||
if(GetPercentageHPLoss(oCreature) <= AI_HEALTH_BLOODY)
|
||||
{
|
||||
if(AI_DEBUG) ai_Debug("ai_polymorphed", "19", "We are wounded and are transforming back!");
|
||||
if(AI_DEBUG) ai_Debug("ai_polymorphed", "20", "We are wounded and are transforming back!");
|
||||
ai_RemoveASpecificEffect(oCreature, EFFECT_TYPE_POLYMORPH);
|
||||
DeleteLocalInt(oCreature, AI_POLYMORPHED);
|
||||
// We need to create the creatures normal forms talent list.
|
||||
DelayCommand(0.0, ai_ClearTalents(oCreature));
|
||||
DelayCommand(0.1, ai_SetCreatureTalents(oCreature, TRUE, TRUE));
|
||||
return;
|
||||
}
|
||||
int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature);
|
||||
@@ -31,25 +36,30 @@ void ai_DoActions(object oCreature, int nForm)
|
||||
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
|
||||
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
|
||||
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
|
||||
object oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee);
|
||||
// If we don't find a target then we don't want to fight anyone!
|
||||
// *************************** RANGED ATTACKS ****************************
|
||||
object oTarget;
|
||||
if(ai_CanIUseRangedWeapon(oCreature, nInMelee))
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ai_SearchForHiddenCreature(oCreature, TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
|
||||
}
|
||||
// **************************** MELEE ATTACKS ****************************
|
||||
oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee);
|
||||
if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
|
||||
else ai_SearchForHiddenCreature(oCreature, TRUE);
|
||||
}
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
// Need to know who we are so we can use thier abilities.
|
||||
int nForm = GetAppearanceType(oCreature);
|
||||
// Check to see if we are back to our normal form?(-1 to get the actual form #)
|
||||
if(nForm == GetLocalInt(oCreature, AI_NORMAL_FORM) - 1)
|
||||
{
|
||||
// If we are transformed back then go back to our primary ai.
|
||||
ai_SetCreatureAIScript(oCreature);
|
||||
DeleteLocalInt(oCreature, AI_NORMAL_FORM);
|
||||
string sAI = GetLocalString(oCreature, AI_COMBAT_SCRIPT);
|
||||
if(sAI == "ai_polymorphed" || sAI == "") sAI = "ai_default";
|
||||
ExecuteScript(sAI, oCreature);
|
||||
}
|
||||
else ai_DoActions(oCreature, nForm);
|
||||
}
|
||||
|
||||
@@ -59,16 +59,16 @@ void main()
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget == ai_GetRangedTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID && ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -45,16 +45,16 @@ void main()
|
||||
if(!nInMelee)
|
||||
{
|
||||
oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
}
|
||||
else
|
||||
{
|
||||
oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
}
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ void main()
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if (ai_TryRangedSneakAttack (oCreature, nInMelee)) return;
|
||||
oTarget = ai_GetNearestTarget (oCreature);
|
||||
oTarget = ai_GetNearestPhysicalTarget (oCreature);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if (ai_TryRapidShotFeat (oCreature, oTarget, nInMelee)) return;
|
||||
|
||||
@@ -38,11 +38,11 @@ void main()
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
string sIndex;
|
||||
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ void main()
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
|
||||
@@ -49,11 +49,11 @@ void main()
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if (!nInMelee) oTarget = ai_GetNearestTarget (oCreature);
|
||||
else oTarget = ai_GetNearestTarget (oCreature, AI_RANGE_MELEE);
|
||||
if (!nInMelee) oTarget = ai_GetNearestPhysicalTarget (oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget (oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
|
||||
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ void main()
|
||||
{
|
||||
if(ai_HasRangedWeaponWithAmmo(oCreature))
|
||||
{
|
||||
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
|
||||
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(!nInMelee) oTarget = ai_GetNearestPhysicalTarget(oCreature);
|
||||
else oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
|
||||
if(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
|
||||
|
||||
@@ -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,7 +59,7 @@ void main()
|
||||
}
|
||||
if(ai_GetIsInCombat(oCreature))
|
||||
{
|
||||
ai_DoAssociateCombatRound (oCreature);
|
||||
ai_DoMonsterCombatRound (oCreature);
|
||||
return;
|
||||
}
|
||||
if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) ai_DetermineSpecialBehavior(oCreature);
|
||||
|
||||
@@ -12,6 +12,7 @@ void ai_MonsterCommands(object oCreature, object oSpeaker, int nMatch);
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
object oLastSpeaker = GetLastSpeaker();
|
||||
ExecuteScript("prc_npc_conv", oCreature);
|
||||
if(AI_DEBUG) ai_Debug("nw_c2_default4", "15", GetName(oCreature) + " listens " +
|
||||
IntToString(GetListenPatternNumber()) + " to " + GetName(GetLastSpeaker()) + "." +
|
||||
@@ -22,7 +23,7 @@ void main()
|
||||
ai_DoMonsterCombatRound(oCreature);
|
||||
return;
|
||||
}
|
||||
object oLastSpeaker = GetLastSpeaker();
|
||||
//object oLastSpeaker = GetLastSpeaker();
|
||||
int nMatch = GetListenPatternNumber();
|
||||
if(nMatch != -1)
|
||||
{
|
||||
|
||||
@@ -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 :
|
||||
{
|
||||
|
||||
@@ -27,7 +27,10 @@ void main()
|
||||
int nSpell = GetLastSpell();
|
||||
if(AI_DEBUG) ai_Debug("nw_ch_acb", "21", GetName(OBJECT_SELF) + " has been hit by a harmful spell(" +
|
||||
Get2DAString("spells", "Label", nSpell) + ")!");
|
||||
if(ai_GetInAOEReaction(oCreature, oCaster, nSpell) &&
|
||||
object oMaster = GetMaster(oCreature);
|
||||
if((!GetLocalInt(oMaster, AI_TARGET_MODE_ON) ||
|
||||
GetLocalObject(oMaster, AI_TARGET_MODE_ASSOCIATE) != oCreature) &&
|
||||
ai_GetInAOEReaction(oCreature, oCaster, nSpell) &&
|
||||
ai_IsInADangerousAOE(oCreature, AI_RANGE_BATTLEFIELD, TRUE)) return;
|
||||
if(ai_GetIsBusy(oCreature)) return;
|
||||
if(ai_CheckForCombat(oCreature, FALSE)) return;
|
||||
|
||||
@@ -26,73 +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)
|
||||
{
|
||||
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)))
|
||||
@@ -114,11 +123,13 @@ void main()
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nLevel));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nMetaMagic));
|
||||
jSpell = JsonArrayInsert(jSpell, JsonInt(nDomain));
|
||||
string sTargetName = ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oTarget, TRUE)));
|
||||
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));
|
||||
jSpell = JsonArrayInsert(jSpells, jSpell);
|
||||
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, 10.0, lLocation, TRUE);
|
||||
while(oTarget != OBJECT_INVALID)
|
||||
{
|
||||
if(sTargetName == ai_RemoveIllegalCharacters(ai_StripColorCodes(GetName(oTarget)))) break;
|
||||
oTarget = GetNextObjectInShape(SHAPE_SPHERE, 10.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;
|
||||
@@ -397,6 +427,7 @@ int GetSpellReady(object oCaster, int nSpell, int nClass, int nLevel, int nMetam
|
||||
if(StringToInt(Get2DAString("classes", "MemorizesSpells", nClass)))
|
||||
{
|
||||
int nSpellMemorized;
|
||||
nMaxIndex = GetMemorizedSpellCountByLevel(oCaster, nClass, nLevel);
|
||||
while(nIndex < nMaxIndex)
|
||||
{
|
||||
nMSpell = GetMemorizedSpellId(oCaster, nClass, nLevel, nIndex);
|
||||
@@ -404,20 +435,18 @@ int GetSpellReady(object oCaster, int nSpell, int nClass, int nLevel, int nMetam
|
||||
{
|
||||
nMmSpell = GetMemorizedSpellMetaMagic(oCaster, nClass, nLevel, nIndex);
|
||||
nDSpell = GetMemorizedSpellIsDomainSpell(oCaster, nClass, nLevel, nIndex);
|
||||
//ai_Debug("pe_buffing", "308", "nMmSpell: " + IntToString(nMmSpell) +
|
||||
//SendMessageToPC(oCaster, "pe_buffing, 308, nSpell: " + IntToString(nSpell) +
|
||||
// " nMSpell: " + IntToString(nMSpell) +
|
||||
// " nMmSpell: " + IntToString(nMmSpell) +
|
||||
// " nMetamagic: " + IntToString(nMetamagic) +
|
||||
// " nDomain: " + IntToString(nDomain) +
|
||||
// " nDSpell: " + IntToString(nDSpell));
|
||||
// Cannot save the domain status so we just use the first spell ID.
|
||||
// Then return the domain statusl.
|
||||
//if(nMmSpell == nMetamagic &&
|
||||
// ((nDomain > 0 && nDSpell == TRUE) || nDomain == 0 && nDSpell == FALSE))
|
||||
if(nMmSpell == nMetamagic)
|
||||
{
|
||||
nSpellMemorized = TRUE;
|
||||
if(GetMemorizedSpellReady(oCaster, nClass, nLevel, nIndex))
|
||||
{
|
||||
if(nDSpell == nDomain) return TRUE;
|
||||
if((nDomain && nDSpell) || (!nDomain && !nDSpell)) return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,18 +454,20 @@ int GetSpellReady(object oCaster, int nSpell, int nClass, int nLevel, int nMetam
|
||||
{
|
||||
sSubRadSpell = "SubRadSpell" + IntToString(nSubRadSpell);
|
||||
if(nSpell == StringToInt(Get2DAString("spells", sSubRadSpell, nMSpell)))
|
||||
nMmSpell = GetMemorizedSpellMetaMagic(oCaster, nClass, nLevel, nIndex);
|
||||
nDSpell = GetMemorizedSpellIsDomainSpell(oCaster, nClass, nLevel, nIndex);
|
||||
ai_Debug("pe_buffing", "421", "nMmSpell: " + IntToString(nMmSpell) +
|
||||
" nMetamagic: " + IntToString(nMetamagic) +
|
||||
" nDomain: " + IntToString(nDomain) +
|
||||
" nDSpell: " + IntToString(nDSpell));
|
||||
if(nMmSpell == nMetamagic)
|
||||
{
|
||||
nSpellMemorized = TRUE;
|
||||
if(GetMemorizedSpellReady(oCaster, nClass, nLevel, nIndex))
|
||||
nMmSpell = GetMemorizedSpellMetaMagic(oCaster, nClass, nLevel, nIndex);
|
||||
nDSpell = GetMemorizedSpellIsDomainSpell(oCaster, nClass, nLevel, nIndex);
|
||||
//SendMessageToPC(oCaster, "pe_buffing, 433, nMmSpell: " + IntToString(nMmSpell) +
|
||||
// " nMetamagic: " + IntToString(nMetamagic) +
|
||||
// " nDomain: " + IntToString(nDomain) +
|
||||
// " nDSpell: " + IntToString(nDSpell));
|
||||
if(nMmSpell == nMetamagic)
|
||||
{
|
||||
if(nDSpell == nDomain) return TRUE;
|
||||
nSpellMemorized = TRUE;
|
||||
if(GetMemorizedSpellReady(oCaster, nClass, nLevel, nIndex))
|
||||
{
|
||||
if((nDomain && nDSpell) || (!nDomain && !nDSpell)) return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,7 +510,6 @@ void PopupWidgetBuffGUIPanel(object oPC)
|
||||
SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE);
|
||||
DelayCommand(0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE));
|
||||
// Row 1 (buttons)**********************************************************
|
||||
|
||||
json jRow = CreateButtonImage(JsonArray(), "ir_level1", "btn_one", 35.0f, 35.0f, 0.0);
|
||||
jRow = CreateButtonImage(jRow, "ir_level2", "btn_two", 35.0f, 35.0f, 0.0);
|
||||
jRow = CreateButtonImage(jRow, "ir_level3", "btn_three", 35.0f, 35.0f, 0.0);
|
||||
@@ -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));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,9 +75,14 @@ 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);
|
||||
int nCurrentAction = GetCurrentAction(oTarget);
|
||||
ai_SendMessages("Current Action: " + IntToString(nCurrentAction), AI_COLOR_RED, oPC);
|
||||
SendMessageToPC(oPC, "Creature Event Scripts:");
|
||||
string sScript = GetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT);
|
||||
sScript += " [" + ResManGetAliasFor(sScript, RESTYPE_NCS) + "]";
|
||||
@@ -507,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")
|
||||
|
||||
@@ -32,6 +32,7 @@ void main()
|
||||
vector vTarget = GetTargetingModeSelectedPosition();
|
||||
location lLocation = Location(GetArea(oPC), vTarget, GetFacing(oPC));
|
||||
object oObject = GetLocalObject(oPC, "AI_TARGET_OBJECT");
|
||||
DeleteLocalString(oPC, AI_TARGET_MODE);
|
||||
// If the user manually exited targeting mode without selecting a target, return
|
||||
if(!GetIsObjectValid(oTarget) && vTarget == Vector())
|
||||
{
|
||||
@@ -327,6 +328,7 @@ void main()
|
||||
if(JsonGetType(jLvlStatList) == JSON_TYPE_NULL)
|
||||
{
|
||||
RemoveHenchman(oPC, oHenchman);
|
||||
ChangeToStandardFaction(oHenchman, STANDARD_FACTION_DEFENDER);
|
||||
// Make sure to get a clean faction version of the henchman here.
|
||||
jHenchman = ObjectToJson(oHenchman, TRUE);
|
||||
jHenchman = CreateLevelStatList(jHenchman, oHenchman, oPC);
|
||||
|
||||
@@ -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");
|
||||
@@ -54,22 +57,30 @@ void main()
|
||||
if(StartingUp(oPC)) return;
|
||||
// Row 1 (Buttons) ********************************************************* 83
|
||||
json jRow = CreateButtonSelect(JsonArray(), "Save", "btn_save", 60.0f, 30.0f, "btn_save_tooltip");
|
||||
CreateButton(jRow, "Clear", "btn_clear", 60.0f, 30.0f, -1.0, "btn_clear_tooltip");
|
||||
CreateButton(jRow, "Buff", "btn_buff", 60.0f, 30.0f, -1.0, "btn_buff_tooltip");
|
||||
CreateButtonSelect(jRow, "List 1", "btn_list1", 60.0f, 30.0f);
|
||||
CreateButtonSelect(jRow, "List 2", "btn_list2", 60.0f, 30.0f);
|
||||
CreateButtonSelect(jRow, "List 3", "btn_list3", 60.0f, 30.0f);
|
||||
CreateButtonSelect(jRow, "List 4", "btn_list4", 60.0f, 30.0f);
|
||||
jRow = CreateButton(jRow, "Clear", "btn_clear", 60.0f, 30.0f, -1.0, "btn_clear_tooltip");
|
||||
jRow = CreateButton(jRow, "Buff", "btn_buff", 60.0f, 30.0f, -1.0, "btn_buff_tooltip");
|
||||
jRow = CreateButtonSelect(jRow, "List 1", "btn_list1", 60.0f, 30.0f);
|
||||
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
|
||||
jRow = JsonArrayInsert(JsonArray(), NuiSpacer());
|
||||
jRow = CreateCheckBox(jRow, "Buff Widget", "buff_widget", 110.0, 30.0f, "buff_widget_tooltip");
|
||||
jRow = CreateCheckBox(jRow, "Lock Widget", "lock_buff_widget", 110.0, 30.0f, "lock_buff_widget_tooltip");
|
||||
if(!AI_SERVER)
|
||||
if(!ai_GetIsServer())
|
||||
{
|
||||
jRow = CreateCheckBox(jRow, "Don't Check for Monsters", "chbx_no_monster_check", 200.0, 30.0f, "chbx_no_monster_check_tooltip");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ai_GetIsDungeonMaster(oPC))
|
||||
{
|
||||
jRow = CreateCheckBox(jRow, "Don't Check for Monsters", "chbx_no_monster_check", 200.0, 30.0f, "chbx_no_monster_check_tooltip");
|
||||
}
|
||||
}
|
||||
jRow = JsonArrayInsert(jRow, NuiSpacer());
|
||||
// Add the row to the column.
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
@@ -96,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)
|
||||
@@ -108,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));
|
||||
@@ -131,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));
|
||||
@@ -143,7 +167,7 @@ void main()
|
||||
NuiSetBindWatch(oPC, nToken, "lock_buff_widget_check", TRUE);
|
||||
sText = " Locks the buffing widget in place reducing its size.";
|
||||
NuiSetBind(oPC, nToken, "lock_buff_widget_tooltip", JsonString(sText));
|
||||
if(!AI_SERVER)
|
||||
if(!ai_GetIsServer())
|
||||
{
|
||||
NuiSetBind(oPC, nToken, "chbx_no_monster_check_event", JsonBool(TRUE));
|
||||
nValue = GetLocalInt(oPC, FB_NO_MONSTER_CHECK);
|
||||
@@ -154,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)
|
||||
@@ -167,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";
|
||||
@@ -182,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));
|
||||
@@ -190,7 +216,6 @@ void main()
|
||||
}
|
||||
nCntr++;
|
||||
}
|
||||
NuiSetBindWatch(oPC, nToken, "window_geometry", TRUE);
|
||||
}
|
||||
int StartingUp(object oPC)
|
||||
{
|
||||
@@ -295,44 +320,55 @@ void PopupWidgetBuffGUIPanel(object oPC)
|
||||
SetLocalInt(oPC, AI_NO_NUI_SAVE, TRUE);
|
||||
DelayCommand(0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE));
|
||||
// Row 1 (buttons)**********************************************************
|
||||
json jRow = JsonArray();
|
||||
CreateButtonImage(jRow, "ir_level1", "btn_one", 35.0f, 35.0f, 0.0);
|
||||
CreateButtonImage(jRow, "ir_level2", "btn_two", 35.0f, 35.0f, 0.0);
|
||||
CreateButtonImage(jRow, "ir_level3", "btn_three", 35.0f, 35.0f, 0.0);
|
||||
CreateButtonImage(jRow, "ir_level4", "btn_four", 35.0f, 35.0f, 0.0);
|
||||
json jRow = CreateButtonImage(JsonArray(), "ir_level1", "btn_one", 35.0f, 35.0f, 0.0);
|
||||
jRow = CreateButtonImage(jRow, "ir_level2", "btn_two", 35.0f, 35.0f, 0.0);
|
||||
jRow = CreateButtonImage(jRow, "ir_level3", "btn_three", 35.0f, 35.0f, 0.0);
|
||||
jRow = CreateButtonImage(jRow, "ir_level4", "btn_four", 35.0f, 35.0f, 0.0);
|
||||
// Add the row to the column.
|
||||
json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow));
|
||||
json jWidget = GetBuffDatabaseJson(oPC, "spells", "menudata");
|
||||
int bAIBuffWidgetLock = JsonGetInt(JsonArrayGet(jWidget, 4));
|
||||
json jMenuData = GetBuffDatabaseJson(oPC, "spells", "menudata");
|
||||
int bAIBuffWidgetLock = JsonGetInt(JsonArrayGet(jMenuData, 4));
|
||||
// Get the window location to restore it from the database.
|
||||
float fX = JsonGetFloat(JsonArrayGet(jWidget, 5));
|
||||
float fY = JsonGetFloat(JsonArrayGet(jWidget, 6));
|
||||
float fX = JsonGetFloat(JsonArrayGet(jMenuData, 5));
|
||||
float fY = JsonGetFloat(JsonArrayGet(jMenuData, 6));
|
||||
if(fX == 0.0f && fY == 0.0f)
|
||||
{
|
||||
fX = 10.0f;
|
||||
fY = 10.0f;
|
||||
}
|
||||
float fGUI_Scale = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0;
|
||||
if(bAIBuffWidgetLock)
|
||||
{
|
||||
fX = fX + 4.0f;
|
||||
fY = fY + 45.0f;
|
||||
fX += 4.0f;
|
||||
// GUI scales are a mess, I just figured them out per scale to keep the widget from moving.
|
||||
if(fGUI_Scale == 1.0) fY += 37.0;
|
||||
else if(fGUI_Scale == 1.1) fY += 38.0;
|
||||
else if(fGUI_Scale == 1.2) fY += 40.0;
|
||||
else if(fGUI_Scale == 1.3) fY += 42.0;
|
||||
else if(fGUI_Scale == 1.4) fY += 43.0;
|
||||
else if(fGUI_Scale == 1.5) fY += 45.0;
|
||||
else if(fGUI_Scale == 1.6) fY += 47.0;
|
||||
else if(fGUI_Scale == 1.7) fY += 48.0;
|
||||
else if(fGUI_Scale == 1.8) fY += 50.0;
|
||||
else if(fGUI_Scale == 1.9) fY += 52.0;
|
||||
else if(fGUI_Scale == 2.0) fY += 54.0;
|
||||
}
|
||||
// Set the layout of the window.
|
||||
json jLayout = NuiCol (jCol);
|
||||
json jLayout = NuiCol(jCol);
|
||||
int nToken;
|
||||
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");
|
||||
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);
|
||||
NuiSetBindWatch (oPC, nToken, "collapsed", TRUE);
|
||||
NuiSetBindWatch (oPC, nToken, "window_geometry", TRUE);
|
||||
// Set the buttons to show events.
|
||||
//NuiSetBind (oPC, nToken, "btn_one", JsonBool (TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_one_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_two", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_two_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_three", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_three_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_four", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_four_event", JsonBool(TRUE));
|
||||
NuiSetBind (oPC, nToken, "btn_one_event", JsonBool (TRUE));
|
||||
NuiSetBind (oPC, nToken, "btn_two", JsonBool (TRUE));
|
||||
NuiSetBind (oPC, nToken, "btn_two_event", JsonBool (TRUE));
|
||||
NuiSetBind (oPC, nToken, "btn_three", JsonBool (TRUE));
|
||||
NuiSetBind (oPC, nToken, "btn_three_event", JsonBool (TRUE));
|
||||
NuiSetBind (oPC, nToken, "btn_four", JsonBool (TRUE));
|
||||
NuiSetBind (oPC, nToken, "btn_four_event", JsonBool (TRUE));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,694 +8,20 @@
|
||||
#include "0i_nui"
|
||||
#include "0i_items"
|
||||
#include "nw_inc_gff"
|
||||
const string CRAFT_JSON = "CRAFT_JSON";
|
||||
const string CRAFT_COOL_DOWN = "CRAFT_COOL_DOWN";
|
||||
const string CRAFT_ITEM_SELECTION = "CRAFT_ITEM_SELECTION";
|
||||
const string CRAFT_MATERIAL_SELECTION = "CRAFT_MATERIAL_SELECTION";
|
||||
const string CRAFT_MODEL_SELECTION = "CRAFT_MODEL_SELECTION";
|
||||
const string CRAFT_COLOR_PALLET = "CRAFT_COLOR_PALLET";
|
||||
const string CRAFT_LEFT_PART_COLOR = "CRAFT_LEFT_PART_COLOR";
|
||||
const string CRAFT_ALL_COLOR = "CRAFT_ALL_COLOR";
|
||||
const string CRAFT_RIGHT_PART_COLOR = "CRAFT_RIGHT_PART_COLOR";
|
||||
const string CRAFT_TARGET = "CRAFT_TARGET";
|
||||
// Tag used in lighting effects.
|
||||
const string CRAFT_HIGHLIGHT = "CRAFT_HIGHLIGHT";
|
||||
const string CRAFT_ULTRALIGHT = "CRAFT_ULTRALIGHT";
|
||||
|
||||
json CreateItemCombo(object oPC, json jRow, string sComboBind);
|
||||
json CreateModelCombo(object oPC, object oTarget, json jRow, string sComboBind);
|
||||
json CreateMaterialCombo(object oPC, json jRow, string sComboBind);
|
||||
// Sets the material buttons for use.
|
||||
// nMaterial 0,1 Cloth 2,3 Leather 4,5 Metal -1 None.
|
||||
void SetMaterialButtons(object oPC, int nToken, int nMaterial);
|
||||
// Returns the correct item based on the crafting menu selected item.
|
||||
object GetSelectedItem(object oTarget, int nItemSelected);
|
||||
int GetArmorModelSelected(object oPC);
|
||||
// Returns True if oItem, nPart has a per part color for sSide.
|
||||
int GetHasPartColor(object oItem, int nPart, string sSide);
|
||||
// Does startup check if the game has just been loaded.
|
||||
int StartingUp(object oPC);
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
object oTarget = GetLocalObject(oPC, CRAFT_TARGET);
|
||||
if(oTarget == OBJECT_INVALID) oTarget = oPC;
|
||||
if(StartingUp(oPC)) return;
|
||||
json jCraft = GetLocalJson(oPC, CRAFT_JSON);
|
||||
if(JsonGetType(jCraft) == JSON_TYPE_NULL) jCraft = JsonObject();
|
||||
// Row 1 (Object Name)****************************************************** 508 / 83
|
||||
json jRow = CreateTextEditBox(JsonArray(), "plc_hold_bind", "txt_item_name", 50, FALSE, 486.0f, 30.0f); // 419
|
||||
json jCol = JsonArrayInsert(JsonArray(), NuiRow(jRow));
|
||||
// Row 2 (Object Name)****************************************************** 508 / 121
|
||||
jRow = JsonArray();
|
||||
if(!AI_SERVER) jRow = CreateButton(jRow, "Information", "btn_info", 160.0f, 30.0f, -1.0, "btn_info_tooltip");
|
||||
else
|
||||
{
|
||||
if(GetIsDM(oTarget))
|
||||
{
|
||||
jRow = CreateButton(jRow, "Information", "btn_info", 160.0f, 30.0f, -1.0, "btn_info_tooltip");
|
||||
}
|
||||
else jRow = JsonArrayInsert(jRow, NuiSpacer());
|
||||
}
|
||||
jRow = CreateButton(jRow, "Wardrobe", "btn_wardrobe", 158.0f, 30.0f, -1.0, "btn_wardrobe_tooltip");
|
||||
jRow = CreateButtonSelect(jRow, "Add Light", "btn_highlight", 160.0f, 30.0f, "btn_highlight_tooltip");
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 3 (Object Name)****************************************************** 508 / 159
|
||||
jRow = CreateButton(JsonArray(), "Save", "btn_save", 160.0f, 30.0f, -1.0, "btn_save_tooltip");
|
||||
jRow = CreateButton(jRow, "Select Target", "btn_select_target", 158.0f, 30.0f);
|
||||
jRow = CreateButton(jRow, "", "btn_cancel", 160.0f, 30.0f, -1.0, "btn_cancel_tooltip");
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 4 (labels)*********************************************************** 508 / 177
|
||||
jRow = CreateLabel(JsonArray(), "Model", "module_title", 143.0f, 10.0f);
|
||||
jRow = CreateLabel(jRow, "Color", "color_title", 339.0f, 10.0f);
|
||||
jRow = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 5 (groups)
|
||||
// Row 51 (title)*********************************************************** 508 / 195 / 18
|
||||
json jGroupRow = CreateLabel(JsonArray(), "Item", "item__cmb_title", 128.0f, 10.0f);
|
||||
json jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow));
|
||||
// Row 52 (combo)*********************************************************** 508 / 233 / 56
|
||||
jGroupRow = CreateItemCombo(oPC, JsonArray(), "item_combo");
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 53 (title)*********************************************************** 508 / 251 / 74
|
||||
jGroupRow = CreateLabel(JsonArray(), "Model", "model_cmb_title",128.0f, 10.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 54 (combo)*********************************************************** 508 / 289 / 112
|
||||
jGroupRow = CreateModelCombo(oPC, oTarget, JsonArray(), "model_combo");
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 55 (title)*********************************************************** 508 / 307 / 120
|
||||
jGroupRow = CreateLabel(JsonArray(), "", "top_title",128.0f, 10.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 56 (top)************************************************************* 508 / 355 / 168
|
||||
jGroupRow = CreateButtonImage(JsonArray(), "nui_shld_left", "btn_prev_t", 40.0f, 40.0f);
|
||||
// Removed TextEditBox for mobile
|
||||
jGroupRow = CreateTextEditBox(jGroupRow, "place_holder", "txt_model_number_t", 3, FALSE, 40.0, 40.0);
|
||||
//CreateLabel(jGroupRow, "", "txt_model_number_t", 40.0, 40.0);
|
||||
jGroupRow = CreateButtonImage(jGroupRow, "nui_shld_right", "btn_next_t", 40.0f, 40.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 57 (title)*********************************************************** 508 / 373 / 186
|
||||
jGroupRow = CreateLabel(JsonArray(), "", "middle_title",128.0f, 10.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 58 (middle)********************************************************** 508 / 421 /234
|
||||
jGroupRow = CreateButtonImage(JsonArray(), "nui_shld_left", "btn_prev_m", 40.0f, 40.0f);
|
||||
// Removed TextEditBox for mobile
|
||||
jGroupRow = CreateTextEditBox(jGroupRow, "place_holder", "txt_model_number_m", 3, FALSE, 40.0, 40.0);
|
||||
//CreateLabel(jGroupRow, "", "txt_model_number_m", 40.0, 40.0);
|
||||
jGroupRow = CreateButtonImage(jGroupRow, "nui_shld_right", "btn_next_m", 40.0f, 40.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 59 (title)*********************************************************** 508 / 439 / 252
|
||||
jGroupRow = CreateLabel(JsonArray(), "", "bottom_title",128.0f, 10.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 510 (bottom)********************************************************* 508 / 487 /300
|
||||
jGroupRow = CreateButtonImage(JsonArray(), "nui_shld_left", "btn_prev_b", 40.0f, 40.0f);
|
||||
// Removed TextEditBox for mobile
|
||||
jGroupRow = CreateTextEditBox(jGroupRow, "place_holder", "txt_model_number_b", 3, FALSE, 40.0, 40.0);
|
||||
//CreateLabel(jGroupRow, "", "txt_model_number_b", 40.0, 40.0);
|
||||
jGroupRow = CreateButtonImage(jGroupRow, "nui_shld_right", "btn_next_b", 40.0f, 40.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 511 (blank spacer)
|
||||
jGroupRow = CreateLabel(JsonArray(), "", "blank_space",128.0f, 20.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 512 (light)********************************************************** 508 / 487 /300
|
||||
jGroupRow = CreateButtonSelect(JsonArray(), "Randomize", "btn_randomize", 128.0f, 30.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiSpacer());
|
||||
jRow = JsonArrayInsert(JsonArray(), NuiHeight(NuiWidth(NuiGroup(NuiCol(jGroupCol)), 143.0), 442.0));
|
||||
// Make the Color Group.
|
||||
// Row 550 (groups)********************************************************* 508 / 361 / 184
|
||||
json jImage = NuiEnabled(NuiId(NuiImage(NuiBind("color_pallet_image"), JsonInt(0), JsonInt(0), JsonInt(1)), "color_pallet"), NuiBind("color_pallet_event"));
|
||||
jImage = NuiWidth(jImage, 320.0); // 256 + 64
|
||||
jImage = NuiHeight(jImage, 220.0); // 176 + 44
|
||||
jImage = NuiTooltip(jImage, NuiBind("color_pallet_tooltip"));
|
||||
json jIndicator = JsonArrayInsert(JsonArray(), NuiDrawListRect(JsonBool(TRUE), NuiColor(255,0,0), JsonBool(FALSE), JsonFloat(2.0), NuiBind("color_pallet_pointer")));
|
||||
jImage = NuiDrawList(jImage, JsonBool(FALSE), jIndicator);
|
||||
jGroupRow = JsonArrayInsert(JsonArray(), jImage);
|
||||
jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow));
|
||||
// Row 551 (groups)********************************************************* 508 / 379 /202
|
||||
jGroupRow = CreateLabel(JsonArray(), "Part To Color", "lbl_color_parts", 320.0f, 10.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 552 (groups)********************************************************* 508 / 417 /240
|
||||
jGroupRow = CreateButtonSelect(JsonArray(), "Right", "btn_right_part_color", 98.0, 30.0, "btn_right_part_color_tooltip");
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "All", "btn_all_color", 98.0, 30.0, "btn_all_color_tooltip");
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "Left", "btn_left_part_color", 98.0, 30.0, "btn_left_part_color_tooltip");
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 553 (groups)********************************************************* 508 / 435 / 258
|
||||
jGroupRow = CreateLabel(JsonArray(), "Part Color To Reset", "lbl_reset_parts", 320.0f, 10.0f);
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 554 (groups)********************************************************* 508 / 473 /296
|
||||
jGroupRow = CreateButton(JsonArray(), "Right", "btn_right_part_reset", 98.0, 30.0, -1.0, "btn_right_part_reset_tooltip");
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButton(jGroupRow, "All", "btn_all_reset", 50.0, 30.0, -1.0, "btn_all_reset_tooltip");
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButton(jGroupRow, "Left", "btn_left_part_reset", 98.0, 30.0, -1.0, "btn_left_part_reset_tooltip");
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
// Row 555 (groups)********************************************************* 508 / 491 / 314
|
||||
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 = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "Leather 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 = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
jGroupRow = CreateButtonSelect(jGroupRow, "Leather 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));
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiSpacer());
|
||||
jRow = JsonArrayInsert(jRow, NuiHeight(NuiWidth(NuiGroup(NuiCol(jGroupCol)), 339.0), 442.0)); // 275 398
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
json jLayout = NuiCol(jCol);
|
||||
// Get the window location to restore it from the database.
|
||||
json jGeometry = JsonObjectGet(jCraft, "CRAFT_MENU");
|
||||
float fX = JsonGetFloat(JsonObjectGet(jGeometry, "x"));
|
||||
float fY = JsonGetFloat(JsonObjectGet(jGeometry, "y"));
|
||||
string sPCWindow;
|
||||
int nToken = SetWindow(oPC, jLayout, "crafting_nui", "Crafting",
|
||||
fX, fY, 508.0, 700.0, FALSE, FALSE, FALSE, FALSE, TRUE, "pe_crafting"); // 444 645
|
||||
// Set all binds, events, and watches.
|
||||
NuiSetBindWatch (oPC, nToken, "window_geometry", TRUE);
|
||||
int nItem = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION));
|
||||
object oItem = GetSelectedItem(oTarget, nItem);
|
||||
// Row 1
|
||||
NuiSetBind(oPC, nToken, "txt_item_name", JsonString(GetName(oItem)));
|
||||
NuiSetBind(oPC, nToken, "txt_item_name_event", JsonBool(TRUE));
|
||||
NuiSetBindWatch(oPC, nToken, "txt_item_name", TRUE);
|
||||
// Row 2
|
||||
NuiSetBind(oPC, nToken, "btn_info_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_info_tooltip", JsonString(" Look at and change item information"));
|
||||
NuiSetBind(oPC, nToken, "btn_wardrobe_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_wardrobe_tooltip", JsonString(" Use your wardrobe to save/load item appearances"));
|
||||
int nLight = GetLocalInt(oPC, CRAFT_HIGHLIGHT) + GetLocalInt(oPC, CRAFT_ULTRALIGHT);
|
||||
NuiSetBind(oPC, nToken, "btn_highlight", JsonBool(nLight));
|
||||
NuiSetBind(oPC, nToken, "btn_highlight_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_highlight_tooltip", JsonString(" Left click for White light, Right click for Ultravision"));
|
||||
// Row 3
|
||||
NuiSetBind(oPC, nToken, "btn_save_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_save_tooltip", JsonString(" Save current changes"));
|
||||
NuiSetBind(oPC, nToken, "btn_select_target_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_cancel_label", JsonString("Exit"));
|
||||
NuiSetBind(oPC, nToken, "btn_cancel_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_cancel_tooltip", JsonString(" Exit the crafting menu"));
|
||||
// Row 4 Labels.
|
||||
// Row 5 Groups.
|
||||
// Row 51 title.
|
||||
// Row 52
|
||||
NuiSetBind(oPC, nToken, "item_combo_selected", JsonInt(nItem));
|
||||
NuiSetBind(oPC, nToken, "item_combo_event", JsonBool(TRUE));
|
||||
NuiSetBindWatch(oPC, nToken, "item_combo_selected", TRUE);
|
||||
// Row 53 title.
|
||||
// Row 54
|
||||
int nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MODEL_SELECTION));
|
||||
if(nItem == 1 || nItem == 2 || nItem == 4)
|
||||
{
|
||||
if(GetHiddenWhenEquipped(oItem)) nSelected = 1;
|
||||
else nSelected = 0;
|
||||
}
|
||||
NuiSetBind(oPC, nToken, "model_combo_selected", JsonInt (nSelected));
|
||||
NuiSetBind(oPC, nToken, "model_combo_event", JsonBool (TRUE));
|
||||
NuiSetBindWatch(oPC, nToken, "model_combo_selected", TRUE);
|
||||
// Row 55, 56, 57 titles
|
||||
// Row 58 top, 59 middle, 510 bottom
|
||||
string sModelTop, sModelMiddle, sModelBottom;
|
||||
// Model Group
|
||||
if(ai_GetIsWeapon(oItem))
|
||||
{
|
||||
int nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, 0);
|
||||
int nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, 0);
|
||||
int nModelNumber = (nModel * 10) + nColor;
|
||||
sModelTop = IntToString(nModelNumber);
|
||||
nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, 1);
|
||||
nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, 1);
|
||||
nModelNumber = (nModel * 10) + nColor;
|
||||
sModelMiddle = IntToString(nModelNumber);
|
||||
nModel = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, 2);
|
||||
nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, 2);
|
||||
nModelNumber = (nModel * 10) + nColor;
|
||||
sModelBottom = IntToString(nModelNumber);
|
||||
// Row 55
|
||||
NuiSetBind(oPC, nToken, "top_title_label", JsonString("Top"));
|
||||
// Row 56
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString(sModelTop));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(TRUE));
|
||||
// Row 57
|
||||
NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Middle"));
|
||||
// Row 58
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelMiddle));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE));
|
||||
// Row 59
|
||||
NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("Bottom"));
|
||||
// Row 510
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(sModelBottom));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(TRUE));
|
||||
// Row 511
|
||||
NuiSetBind(oPC, nToken, "btn_randomize_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_randomize_tooltip", JsonString(" Randomize the selected weapon"));
|
||||
}
|
||||
// Armor and clothing
|
||||
else if(nItem == 0)
|
||||
{
|
||||
nSelected = GetArmorModelSelected(oPC);
|
||||
// These models only have one side so make sure we are not linked.
|
||||
if (nSelected == ITEM_APPR_ARMOR_MODEL_NECK ||
|
||||
nSelected == ITEM_APPR_ARMOR_MODEL_TORSO ||
|
||||
nSelected == ITEM_APPR_ARMOR_MODEL_BELT ||
|
||||
nSelected == ITEM_APPR_ARMOR_MODEL_PELVIS ||
|
||||
nSelected == ITEM_APPR_ARMOR_MODEL_ROBE)
|
||||
{
|
||||
sModelMiddle = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nSelected));
|
||||
// Row 55
|
||||
NuiSetBind(oPC, nToken, "top_title_label", JsonString(""));
|
||||
// Row 56
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_name_t", JsonString(""));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(FALSE));
|
||||
// Row 57
|
||||
NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Model"));
|
||||
// Row 58
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelMiddle));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE));
|
||||
// Row 59
|
||||
NuiSetBind(oPC, nToken, "bottom_title_label", JsonString(""));
|
||||
// Row 510
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(""));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(FALSE));
|
||||
}
|
||||
else
|
||||
{
|
||||
sModelTop = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nSelected));
|
||||
if(nSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nSelected--;
|
||||
else nSelected++;
|
||||
sModelBottom = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nSelected));
|
||||
// Row 55
|
||||
NuiSetBind(oPC, nToken, "top_title_label", JsonString("Right"));
|
||||
// Row 56
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString(sModelTop));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(TRUE));
|
||||
// Row 57
|
||||
NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Right & Left"));
|
||||
// Row 58
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelTop));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE));
|
||||
// Row 59
|
||||
NuiSetBind(oPC, nToken, "bottom_title_label", JsonString("Left"));
|
||||
// Row 510
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(sModelBottom));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(TRUE));
|
||||
}
|
||||
// Row 511
|
||||
NuiSetBind(oPC, nToken, "btn_randomize_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_randomize_tooltip", JsonString(" Randomize the selected armor"));
|
||||
}
|
||||
// Shields, Cloaks, and Helmets.
|
||||
else
|
||||
{
|
||||
sModelMiddle = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0));
|
||||
// Row 55
|
||||
NuiSetBind(oPC, nToken, "top_title_label", JsonString(""));
|
||||
// Row 56
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_t_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_t", JsonString(""));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_t_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_t_event", JsonBool(FALSE));
|
||||
// Row 57
|
||||
NuiSetBind(oPC, nToken, "middle_title_label", JsonString("Model"));
|
||||
// Row 58
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_m_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_m", JsonString(sModelMiddle));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_m_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_m_event", JsonBool(TRUE));
|
||||
// Row 59
|
||||
NuiSetBind(oPC, nToken, "bottom_title_label", JsonString(""));
|
||||
// Row 510
|
||||
//NuiSetBind(oPC, nToken, "txt_model_number_b_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "txt_model_number_b", JsonString(""));
|
||||
NuiSetBind(oPC, nToken, "btn_prev_b_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_next_b_event", JsonBool(FALSE));
|
||||
// Row 511
|
||||
NuiSetBind(oPC, nToken, "btn_randomize_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_randomize_tooltip", JsonString(" Randomize the selected item"));
|
||||
}
|
||||
// Color Group
|
||||
if(ai_GetIsWeapon(oItem) || ai_GetIsShield(oItem))
|
||||
{
|
||||
// Need to disable the color widgets.
|
||||
// Row 511
|
||||
NuiSetBind(oPC, nToken, "color_pallet_image", JsonString("gui_pal_tattoo"));
|
||||
NuiSetBind(oPC, nToken, "color_pallet_image_event", JsonBool(FALSE));
|
||||
// Row 512 - Label Part to Color
|
||||
// Row 5l3
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(FALSE));
|
||||
// Row 514 - Label Part Color to Reset
|
||||
// Row 515
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE));
|
||||
// Row 516 - Label Material to Color
|
||||
// Row 517
|
||||
NuiSetBind(oPC, nToken, "btn_material_0", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_material_2", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_material_4", JsonBool(FALSE));
|
||||
// Row 518
|
||||
NuiSetBind(oPC, nToken, "btn_material_1", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_material_3", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_material_5", JsonBool(FALSE));
|
||||
SetMaterialButtons(oPC, nToken, -1);
|
||||
}
|
||||
// Armor and clothing
|
||||
else if(nItem == 0)
|
||||
{
|
||||
// Row 511
|
||||
string sColorPallet = GetLocalString(oPC, CRAFT_COLOR_PALLET);
|
||||
if(sColorPallet == "") sColorPallet = "gui_pal_tattoo";
|
||||
int nMaterialSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION));
|
||||
int nModelSelected = GetArmorModelSelected(oPC);
|
||||
// Row 511
|
||||
NuiSetBind(oPC, nToken, "color_pallet_image", JsonString(sColorPallet));
|
||||
NuiSetBind(oPC, nToken, "color_pallet_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "color_pallet_tooltip", JsonString(" Select a color or use the mouse wheel"));
|
||||
int nSelectedRight, nSelectedAll, nSelectedLeft;
|
||||
string sColorAll = IntToString(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected));
|
||||
// These models only have one side so make sure we are not linked.
|
||||
if (nModelSelected == ITEM_APPR_ARMOR_MODEL_NECK ||
|
||||
nModelSelected == ITEM_APPR_ARMOR_MODEL_TORSO ||
|
||||
nModelSelected == ITEM_APPR_ARMOR_MODEL_BELT ||
|
||||
nModelSelected == ITEM_APPR_ARMOR_MODEL_PELVIS ||
|
||||
nModelSelected == ITEM_APPR_ARMOR_MODEL_ROBE)
|
||||
{
|
||||
// Row 512 - Label Part to Color
|
||||
// Row 5l3
|
||||
int nPartColor = GetHasPartColor(oItem, nModelSelected, "Right");
|
||||
nSelectedRight = JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR));
|
||||
if(!nSelectedRight && nPartColor)
|
||||
{
|
||||
nSelectedRight = TRUE;
|
||||
nSelectedLeft = FALSE;
|
||||
}
|
||||
nSelectedAll = !nSelectedRight;
|
||||
jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonBool(nSelectedAll));
|
||||
jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonBool(nSelectedRight));
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(nSelectedRight));
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(nSelectedAll));
|
||||
NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(FALSE));
|
||||
// Row 514 - Label Part Color to Reset
|
||||
// Row 5l5
|
||||
nSelectedRight = GetHasPartColor(oItem, nModelSelected, "Right");
|
||||
nSelectedAll = nSelectedRight;
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(nSelectedRight));
|
||||
NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(nSelectedAll));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Row 512 - Label Part to Color
|
||||
// Row 5l3
|
||||
int nPartColor = GetHasPartColor(oItem, nModelSelected, "Right");
|
||||
nSelectedRight = JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR));
|
||||
if(!nSelectedRight && nPartColor)
|
||||
{
|
||||
nSelectedRight = TRUE;
|
||||
nSelectedLeft = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nPartColor = GetHasPartColor(oItem, nModelSelected, "Left");
|
||||
nSelectedLeft = JsonGetInt(JsonObjectGet(jCraft, CRAFT_LEFT_PART_COLOR));
|
||||
if(!nSelectedLeft && nPartColor)
|
||||
{
|
||||
nSelectedLeft = TRUE;
|
||||
nSelectedRight = FALSE;
|
||||
}
|
||||
}
|
||||
nSelectedAll = !nSelectedRight && !nSelectedLeft;
|
||||
jCraft = JsonObjectSet(jCraft, CRAFT_LEFT_PART_COLOR, JsonBool(nSelectedLeft));
|
||||
jCraft = JsonObjectSet(jCraft, CRAFT_ALL_COLOR, JsonBool(nSelectedAll));
|
||||
jCraft = JsonObjectSet(jCraft, CRAFT_RIGHT_PART_COLOR, JsonBool(nSelectedRight));
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_color", JsonBool(nSelectedRight));
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(nSelectedAll));
|
||||
NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(nSelectedLeft));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(TRUE));
|
||||
// Row 514 - Label Part Color to Reset
|
||||
// Row 5l5
|
||||
nSelectedRight = GetHasPartColor(oItem, nModelSelected, "Right");
|
||||
nSelectedLeft = GetHasPartColor(oItem, nModelSelected, "Left");
|
||||
nSelectedAll = nSelectedRight || nSelectedLeft;
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(nSelectedRight));
|
||||
NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(nSelectedAll));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(nSelectedLeft));
|
||||
}
|
||||
int nColor;
|
||||
if(!JsonGetInt(NuiGetBind(oPC, nToken, "btn_all_color")))
|
||||
{
|
||||
int nModelSelected = GetArmorModelSelected(oPC);
|
||||
if(!JsonGetInt(JsonObjectGet(jCraft, CRAFT_RIGHT_PART_COLOR)))
|
||||
{
|
||||
// Note: Right Thigh and Left Thigh are backwards so this fixes that!
|
||||
if (nModelSelected == ITEM_APPR_ARMOR_MODEL_RTHIGH) nModelSelected--;
|
||||
else nModelSelected++;
|
||||
}
|
||||
int nIndex = ITEM_APPR_ARMOR_NUM_COLORS + (nModelSelected * ITEM_APPR_ARMOR_NUM_COLORS) + nMaterialSelected;
|
||||
nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nIndex);
|
||||
}
|
||||
else nColor = 255;
|
||||
if(nColor == 255) nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected);
|
||||
float fPointX = IntToFloat((nColor - ((nColor / 16) * 16)) * 20);
|
||||
float fPointY = IntToFloat((nColor / 16) * 20);
|
||||
NuiSetBind(oPC, nToken, "color_pallet_pointer", NuiRect(fPointX, fPointY, 20.0, 20.0));
|
||||
// Row 516 - Label Material to Color
|
||||
// Row 517 & 518
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_color_tooltip", JsonString(" Select the right part to be uniquely colored"));
|
||||
NuiSetBind(oPC, nToken, "btn_all_color_tooltip", JsonString(" Select all parts to be colored"));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_color_tooltip", JsonString(" Select the left part to be uniquely colored"));
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_reset_tooltip", JsonString(" Clears the right part's unique color"));
|
||||
NuiSetBind(oPC, nToken, "btn_all_reset_tooltip", JsonString(" Clears all parts unique colors"));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_reset_tooltip", JsonString(" Clears the left part's unique color"));
|
||||
nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION));
|
||||
SetMaterialButtons(oPC, nToken, nSelected);
|
||||
SetLocalJson(oPC, CRAFT_JSON, jCraft);
|
||||
}
|
||||
// Cloaks and Helmets.
|
||||
else
|
||||
{
|
||||
// Row 511
|
||||
string sColorPallet = GetLocalString(oPC, CRAFT_COLOR_PALLET);
|
||||
if(sColorPallet == "") sColorPallet = "gui_pal_tattoo";
|
||||
int nMaterialSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION));
|
||||
int nModelSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MODEL_SELECTION));
|
||||
int nColor = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nMaterialSelected);
|
||||
float fPointX = IntToFloat((nColor - ((nColor / 16) * 16)) * 20);
|
||||
float fPointY = IntToFloat((nColor / 16) * 20);
|
||||
NuiSetBind(oPC, nToken, "color_pallet_pointer", NuiRect(fPointX, fPointY, 20.0, 20.0));
|
||||
NuiSetBind(oPC, nToken, "color_pallet_image", JsonString(sColorPallet));
|
||||
NuiSetBind(oPC, nToken, "color_pallet_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "color_pallet_tooltip", JsonString(" Select a color or use the mouse wheel"));
|
||||
// Row 512 - Label Part to Color
|
||||
// Row 5l3
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_color_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_all_color_event", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_all_color", JsonBool(TRUE));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_color_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_color", JsonBool(FALSE));
|
||||
// Row 514 - Label Part Color to Reset
|
||||
// Row 5l5
|
||||
NuiSetBind(oPC, nToken, "btn_right_part_reset_event", JsonBool(FALSE));
|
||||
//NuiSetBind(oPC, nToken, "btn_all_reset_event", JsonBool(FALSE));
|
||||
NuiSetBind(oPC, nToken, "btn_left_part_reset_event", JsonBool(FALSE));
|
||||
// Row 516 - Label Material to Color
|
||||
// Row 517 & 518
|
||||
nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MATERIAL_SELECTION));
|
||||
SetMaterialButtons(oPC, nToken, nSelected);
|
||||
}
|
||||
// Lets make sure we clean up any cool down variables.
|
||||
//DeleteLocalInt(oPC, CRAFT_COOL_DOWN);
|
||||
}
|
||||
json CreateItemCombo(object oPC, json jRow, string sComboBind)
|
||||
{
|
||||
int nCnt;
|
||||
// Create the list.
|
||||
json jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Armor", 0));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Cloak", 1));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Headgear", 2));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Right hand", 3));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Left hand", 4));
|
||||
return CreateCombo(jRow, jCombo, sComboBind, 128.0, 40.0);
|
||||
}
|
||||
json CreateModelCombo(object oPC, object oTarget, json jRow, string sComboBind)
|
||||
{
|
||||
float fFacing = GetFacing(oTarget);
|
||||
json jCombo, jCraft = GetLocalJson(oPC, CRAFT_JSON);
|
||||
int nSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_ITEM_SELECTION));
|
||||
// Create the list.
|
||||
// Armor.
|
||||
if(nSelected == 0)
|
||||
{
|
||||
fFacing += 180.0f;
|
||||
if (fFacing > 359.0) fFacing -=359.0;
|
||||
AssignCommand(oPC, SetCameraFacing(fFacing, 4.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST));
|
||||
jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Neck", 0));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Shoulder", 1));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Bicep", 2));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Forearm", 3));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Hand", 4));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Torso", 5));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Belt", 6));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Pelvis", 7));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Thigh", 8));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Shin", 9));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Foot", 10));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Robe", 11));
|
||||
}
|
||||
// Cloak.
|
||||
else if(nSelected == 1)
|
||||
{
|
||||
if(fFacing > 359.0) fFacing -=359.0;
|
||||
AssignCommand (oPC, SetCameraFacing(fFacing, 4.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST));
|
||||
jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Cloak", 0));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Invisible", 1));
|
||||
}
|
||||
// Headgear.
|
||||
else if (nSelected == 2)
|
||||
{
|
||||
fFacing += 180.0f;
|
||||
if(fFacing > 359.0) fFacing -=359.0;
|
||||
AssignCommand(oPC, SetCameraFacing(fFacing, 2.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST));
|
||||
jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Headgear", 0));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Invisible", 1));
|
||||
}
|
||||
// Weapon.
|
||||
else if (nSelected == 3)
|
||||
{
|
||||
// If they are changing a bow then face the opposite side.
|
||||
object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
int nBaseItemType = GetBaseItemType(oItem);
|
||||
if(nBaseItemType == BASE_ITEM_LONGBOW || nBaseItemType == BASE_ITEM_SHORTBOW) fFacing -= 90.00;
|
||||
// This will make the camera face a melee weapon.
|
||||
else fFacing += 90.0;
|
||||
if(fFacing > 359.0) fFacing -=359.0;
|
||||
AssignCommand(oPC, SetCameraFacing(fFacing, 3.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST));
|
||||
jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Weapon", 0));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Acidic", 1));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Frost", 2));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Electric", 3));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Unholy", 4));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Flaming", 5));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Holy", 6));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Sonic", 7));
|
||||
}
|
||||
// Weapon/Shield.
|
||||
else if(nSelected == 4)
|
||||
{
|
||||
fFacing += 270.0f;
|
||||
if(fFacing > 359.0) fFacing -=359.0;
|
||||
AssignCommand(oPC, SetCameraFacing(fFacing, 3.5f, 75.0, CAMERA_TRANSITION_TYPE_VERY_FAST));
|
||||
object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
|
||||
if(ai_GetIsShield(oItem))
|
||||
{
|
||||
jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Shield", 0));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Invisible", 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
jCombo = JsonArrayInsert(JsonArray(), NuiComboEntry("Weapon", 0));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Acidic", 1));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Frost", 2));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Electric", 3));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Unholy", 4));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Flaming", 5));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Holy", 6));
|
||||
jCombo = JsonArrayInsert(jCombo, NuiComboEntry("Sonic", 7));
|
||||
}
|
||||
}
|
||||
return CreateCombo(jRow, jCombo, sComboBind, 128.0, 40.0);
|
||||
}
|
||||
void SetMaterialButtons(object oPC, int nToken, int nMaterial)
|
||||
{
|
||||
int nIndex, bBool, bUseable;
|
||||
string sIndex;
|
||||
if(nMaterial > -1) bUseable = TRUE;
|
||||
for(nIndex = 0;nIndex < 6;nIndex++)
|
||||
{
|
||||
if(nIndex == nMaterial) bBool = TRUE;
|
||||
else bBool = FALSE;
|
||||
sIndex = IntToString(nIndex);
|
||||
NuiSetBind(oPC, nToken, "btn_material_" + sIndex + "_event", JsonBool(bUseable));
|
||||
NuiSetBind(oPC, nToken, "btn_material_" + sIndex, JsonBool(bBool));
|
||||
}
|
||||
}
|
||||
object GetSelectedItem(object oTarget, int nItemSelected)
|
||||
{
|
||||
if(nItemSelected == 0) return GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
|
||||
else if(nItemSelected == 1) return GetItemInSlot(INVENTORY_SLOT_CLOAK, oTarget);
|
||||
else if(nItemSelected == 2) return GetItemInSlot(INVENTORY_SLOT_HEAD, oTarget);
|
||||
else if(nItemSelected == 3) return GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||
else if(nItemSelected == 4) return GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
int GetArmorModelSelected(object oPC)
|
||||
{
|
||||
json jCraft = GetLocalJson(oPC, CRAFT_JSON);
|
||||
int nModelSelected = JsonGetInt(JsonObjectGet(jCraft, CRAFT_MODEL_SELECTION));
|
||||
if(nModelSelected == 0) return ITEM_APPR_ARMOR_MODEL_NECK;
|
||||
if(nModelSelected == 1) return ITEM_APPR_ARMOR_MODEL_RSHOULDER;
|
||||
if(nModelSelected == 2) return ITEM_APPR_ARMOR_MODEL_RBICEP;
|
||||
if(nModelSelected == 3) return ITEM_APPR_ARMOR_MODEL_RFOREARM;
|
||||
if(nModelSelected == 4) return ITEM_APPR_ARMOR_MODEL_RHAND;
|
||||
if(nModelSelected == 5) return ITEM_APPR_ARMOR_MODEL_TORSO;
|
||||
if(nModelSelected == 6) return ITEM_APPR_ARMOR_MODEL_BELT;
|
||||
if(nModelSelected == 7) return ITEM_APPR_ARMOR_MODEL_PELVIS;
|
||||
if(nModelSelected == 8) return ITEM_APPR_ARMOR_MODEL_RTHIGH;
|
||||
if(nModelSelected == 9) return ITEM_APPR_ARMOR_MODEL_RSHIN;
|
||||
if(nModelSelected == 10) return ITEM_APPR_ARMOR_MODEL_RFOOT;
|
||||
return ITEM_APPR_ARMOR_MODEL_ROBE;
|
||||
}
|
||||
int GetHasPartColor(object oItem, int nPart, string sSide)
|
||||
{
|
||||
json jItem = ObjectToJson(oItem);
|
||||
string sPartName = "APart_";
|
||||
if(sSide == "Left")
|
||||
{
|
||||
// Note: Right Thigh and Left Thigh are backwards so this fixes that!
|
||||
if (nPart == ITEM_APPR_ARMOR_MODEL_RTHIGH) nPart--;
|
||||
else nPart++;
|
||||
}
|
||||
sPartName += IntToString(nPart) + "_Col_";
|
||||
int nPartColor = JsonGetInt(GffGetByte(jItem, sPartName + "0"));
|
||||
nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "1"));
|
||||
nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "2"));
|
||||
nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "3"));
|
||||
nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "4"));
|
||||
nPartColor += JsonGetInt(GffGetByte(jItem, sPartName + "5"));
|
||||
return nPartColor;
|
||||
// Set this variable on the player so PEPS can run the targeting script for this plugin.
|
||||
SetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT, "pe_crafting");
|
||||
// Set Targeting variables.
|
||||
SetLocalString(oPC, AI_TARGET_MODE, "SELECT_TARGET");
|
||||
ai_SendMessages("Select your charcter, a henchman or an item possessed by one.", AI_COLOR_YELLOW, oPC);
|
||||
EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE | OBJECT_TYPE_ITEM , MOUSECURSOR_EXAMINE, MOUSECURSOR_NOEXAMINE);
|
||||
|
||||
}
|
||||
int StartingUp(object oPC)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ void main()
|
||||
//SetLocalInt (oPC, AI_NO_NUI_SAVE, TRUE);
|
||||
//DelayCommand (0.5f, DeleteLocalInt (oPC, AI_NO_NUI_SAVE));
|
||||
string sText = " [Single player]";
|
||||
if(AI_SERVER) sText = " [Server]";
|
||||
if(ai_GetIsServer()) sText = " [Server]";
|
||||
// ************************************************************************* Width / Height
|
||||
// Row 1 ******************************************************************* 500 / 73
|
||||
json jRow = JsonArrayInsert(JsonArray(), NuiSpacer());
|
||||
@@ -30,25 +30,31 @@ void main()
|
||||
// Add row to the column.
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
// Row 3 ******************************************************************* 500 / 101
|
||||
sText = "Monster AI (nw_c2_default1): " + ResManGetAliasFor("nw_c2_default1", RESTYPE_NCS);
|
||||
jRow = CreateLabel(JsonArray(), sText, "monster_1_ai", 470.0f, 20.0f, NUI_HALIGN_CENTER);
|
||||
// Add row to the column.
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
sText = ResManGetAliasFor("nw_c2_default1", RESTYPE_NCS);
|
||||
if(sText != "")
|
||||
{
|
||||
jRow = CreateLabel(JsonArray(), "Monster AI (nw_c2_default1): " + sText, "monster_1_ai", 470.0f, 20.0f);
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
}
|
||||
// Row 4 ******************************************************************* 500 / 157
|
||||
sText = "Monster AI (j_ai_onheartbeat): " + ResManGetAliasFor("j_ai_onheartbeat", RESTYPE_NCS);
|
||||
jRow = CreateLabel(JsonArray(), sText, "monster_2_ai", 470.0f, 20.0f, NUI_HALIGN_CENTER);
|
||||
// Add row to the column.
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
sText = ResManGetAliasFor("j_ai_onheartbeat", RESTYPE_NCS);
|
||||
if(sText != "")
|
||||
{
|
||||
jRow = CreateLabel(JsonArray(), "Monster AI (j_ai_onheartbeat): " + sText, "monster_2_ai", 470.0f, 20.0f);
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
}
|
||||
// Row 5 ******************************************************************* 500 / 213
|
||||
sText = "Associate AI (nw_ch_ac1): " + ResManGetAliasFor("nw_ch_ac1", RESTYPE_NCS);
|
||||
jRow = CreateLabel(JsonArray(), sText, "henchman_ai", 470.0f, 20.0f, NUI_HALIGN_CENTER);
|
||||
// Add row to the column.
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
sText = ResManGetAliasFor("nw_ch_ac1", RESTYPE_NCS);
|
||||
if(sText != "")
|
||||
{
|
||||
jRow = CreateLabel(JsonArray(), "Associate AI (nw_ch_ac1): " + sText, "henchman_ai", 470.0f, 20.0f);
|
||||
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
|
||||
}
|
||||
// Row 6 ******************************************************************* 500 / 241
|
||||
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());
|
||||
@@ -146,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
|
||||
|
||||
@@ -369,11 +369,12 @@ void RemoveYourHenchman(object oPC, int nToken, string sParty)
|
||||
else
|
||||
{
|
||||
RemoveHenchman(oPC, oHenchman);
|
||||
ChangeToStandardFaction(oHenchman, STANDARD_FACTION_DEFENDER);
|
||||
AssignCommand(oHenchman, SetIsDestroyable(TRUE, FALSE, FALSE));
|
||||
NuiDestroy(oPC, NuiFindWindow(oPC, ai_GetAssociateType(oPC, oHenchman) + AI_WIDGET_NUI));
|
||||
DestroyObject(oHenchman);
|
||||
ai_SendMessages(GetName(oHenchman) + " has been removed from the party!", AI_COLOR_GREEN, oPC);
|
||||
}
|
||||
ai_SendMessages(GetName(oHenchman) + " has been removed from the party!", AI_COLOR_GREEN, oPC);
|
||||
NuiDestroy(oPC, nToken);
|
||||
ExecuteScript("pi_henchmen", oPC);
|
||||
}
|
||||
@@ -388,6 +389,7 @@ void RemoveWholeParty(object oPC, int nToken, string sParty)
|
||||
{
|
||||
ai_SendMessages(GetName(oHenchman) + " has been remove from your Party.", AI_COLOR_YELLOW, oPC);
|
||||
RemoveHenchman(oPC, oHenchman);
|
||||
ChangeToStandardFaction(oHenchman, STANDARD_FACTION_DEFENDER);
|
||||
AssignCommand(oHenchman, SetIsDestroyable(TRUE, FALSE, FALSE));
|
||||
NuiDestroy(oPC, NuiFindWindow(oPC, ai_GetAssociateType(oPC, oHenchman) + AI_WIDGET_NUI));
|
||||
DestroyObject(oHenchman);
|
||||
@@ -426,10 +428,20 @@ void SaveYourHenchman(object oPC, int nToken, string sParty)
|
||||
ChangeToStandardFaction(oHenchman, STANDARD_FACTION_DEFENDER);
|
||||
json jHenchman = ObjectToJson(oHenchman, TRUE);
|
||||
if(!bPC) AddHenchman(oPC, oHenchman);
|
||||
else DestroyObject(oHenchman);
|
||||
//string sPatch = "[{\"op\":\"replace\",\"path\":\"/FactionID/value\",\"value\":1}]";
|
||||
//json jPatch = JsonParse(sPatch);
|
||||
//jHenchman = JsonPatch(jHenchman, jPatch);
|
||||
else
|
||||
{
|
||||
DestroyObject(oHenchman);
|
||||
// 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);
|
||||
SetHenchmanDbString(oPC, "henchname", sHenchmanName, sSlot);
|
||||
@@ -450,15 +462,13 @@ 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++;
|
||||
}
|
||||
if(nIndex == nMaxHenchman) ai_SendMessages("This party is full!", AI_COLOR_RED, oPC);
|
||||
NuiDestroy(oPC, nToken);
|
||||
ExecuteScript("pi_henchmen", oPC);
|
||||
if(nIndex == nMaxHenchman) ai_SendMessages("This party is full!", AI_COLOR_RED, oPC);
|
||||
}
|
||||
void SaveWholeParty(object oPC, int nToken, string sParty)
|
||||
{
|
||||
@@ -672,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++;
|
||||
}
|
||||
@@ -814,10 +821,25 @@ 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 CanSelectFeat(json jCreature, object oCreature, int nFeat, int nPosition = 1)
|
||||
int GetHasJFeat(int nFeat, json jFeatList)
|
||||
{
|
||||
int nIndex, nJFeat, nMaxFeats = JsonGetLength(jFeatList);
|
||||
json jFeat;
|
||||
//WriteTimestampedLogEntry("pinc_henchmen, 831, nFeat: " + IntToString(nFeat) + " nMaxFeats: " + IntToString(nMaxFeats) + ".");
|
||||
while(nIndex < nMaxFeats)
|
||||
{
|
||||
jFeat = JsonArrayGet(jFeatList, nIndex);
|
||||
nJFeat = JsonGetInt(GffGetWord(jFeat, "Feat"));
|
||||
//WriteTimestampedLogEntry("pinc_henchmen, 831, nJFeat: " + IntToString(nJFeat) + ".");
|
||||
if(nJFeat == nFeat) return TRUE;
|
||||
nIndex++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
int CanSelectFeat(json jCreature, object oCreature, int nFeat, json jFeats, int nPosition = 1)
|
||||
{
|
||||
// Check if all classes can use.
|
||||
int n2DAStat = StringToInt(Get2DAString("feat", "ALLCLASSESCANUSE", nFeat));
|
||||
@@ -855,28 +877,30 @@ int CanSelectFeat(json jCreature, object oCreature, int nFeat, int nPosition = 1
|
||||
n2DAStat = StringToInt(Get2DAString("feat", "MINSPELLLVL", nFeat));
|
||||
int nSpellLevel = 0, nClass = GetClassByPosition(nPosition, oCreature);
|
||||
string s2DAName = Get2DAString("classes", "SpellGainTable", nClass);
|
||||
int nLevel = GetLevelByPosition(nPosition, oCreature);
|
||||
if(s2DAName != "")
|
||||
{
|
||||
int nLevel = GetLevelByPosition(nPosition, oCreature);
|
||||
nSpellLevel = StringToInt(Get2DAString(s2DAName, "NumSpellLevels", nLevel - 1)) - 1;
|
||||
if(nSpellLevel < 0) nSpellLevel = 0;
|
||||
}
|
||||
if(nSpellLevel < n2DAStat) return FALSE;
|
||||
n2DAStat = StringToInt(Get2DAString("feat", "PREREQFEAT1", nFeat));
|
||||
if(n2DAStat > 0)
|
||||
if(n2DAStat > 0 && GetHasJFeat(n2DAStat, jFeats))
|
||||
{
|
||||
// ************************************** Add code to search jCreature's feats!
|
||||
if(!GetHasFeat(n2DAStat, oCreature)) return FALSE;
|
||||
n2DAStat = StringToInt(Get2DAString("feat", "PREREQFEAT2", nFeat));
|
||||
if(!GetHasFeat(n2DAStat, oCreature)) return FALSE;
|
||||
if(n2DAStat > 0 && !GetHasJFeat(n2DAStat, jFeats)) return FALSE;
|
||||
}
|
||||
int nIndex;
|
||||
while(nIndex < 5)
|
||||
{
|
||||
n2DAStat = StringToInt(Get2DAString("feat", "OrReqFeat" + IntToString(nIndex), nFeat));
|
||||
if(nIndex == 0 && n2DAStat == 0) break;
|
||||
if(GetHasFeat(n2DAStat, oCreature)) break;
|
||||
nIndex++;
|
||||
if(nIndex == 5) return FALSE;
|
||||
if(n2DAStat > 0)
|
||||
{
|
||||
if(GetHasJFeat(n2DAStat, jFeats)) break;
|
||||
}
|
||||
else return FALSE;
|
||||
++nIndex;
|
||||
}
|
||||
string s2DAStat = Get2DAString("feat", "REQSKILL", nFeat);
|
||||
if(s2DAStat != "")
|
||||
@@ -969,7 +993,7 @@ json ResetFeats(json jHenchman, object oHenchman)
|
||||
int nRace = GetRacialType(oHenchman);
|
||||
string sRace2DAName = Get2DAString("racialtypes", "FeatsTable", nRace);
|
||||
// Give racial feats.
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 972, Checking for racial feats.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 996, Checking for racial feats.");
|
||||
int nRaceRow, nRaceFeat;
|
||||
int nRaceMaxRow = Get2DARowCount(sRace2DAName);
|
||||
while(nRaceRow < nRaceMaxRow)
|
||||
@@ -979,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, 982, Adding racial feat: " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 999, Adding racial feat: " +
|
||||
Get2DAString("feat", "LABEL", nRaceFeat));
|
||||
nRaceRow++;
|
||||
}
|
||||
// Give class feats.
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 972, 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);
|
||||
@@ -1002,17 +1026,17 @@ 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, 1005, Adding class feat: " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1022, Adding class feat: " +
|
||||
Get2DAString("feat", "LABEL", nClassFeat));
|
||||
}
|
||||
}
|
||||
nClassRow++;
|
||||
}
|
||||
// Give any bonus feats from package.
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1012, Checking for selectable feats.");
|
||||
int nPackageFeat, nPackageRow;
|
||||
string sBonusFeat2DAName = Get2DAString("classes", "BonusFeatsTable", nClass);
|
||||
int nNumOfFeats = StringToInt(Get2DAString(sBonusFeat2DAName, "Bonus", nLevel));
|
||||
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.
|
||||
@@ -1029,13 +1053,13 @@ json ResetFeats(json jHenchman, object oHenchman)
|
||||
if(nClassFeat == nPackageFeat)
|
||||
{
|
||||
sList = Get2DAString(sClsFeat2DAName, "List", nClassRow);
|
||||
if((sList == "1" || sList == "2") && CanSelectFeat(jHenchman, oHenchman, nClassFeat))
|
||||
if((sList == "1" || sList == "2") && CanSelectFeat(jHenchman, oHenchman, nClassFeat, jFeatList))
|
||||
{
|
||||
jFeat = JsonObject();
|
||||
jFeat = GffAddWord(jFeat, "Feat", nClassFeat);
|
||||
jFeat = JsonObjectSet(jFeat, "__struct_id", JsonInt(1));
|
||||
jFeatList = JsonArrayInsert(jFeatList, jFeat);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1028, Adding class bonus feat: " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1055, Adding class bonus feat: " +
|
||||
Get2DAString("feat", "LABEL", nPackageFeat));
|
||||
nNumOfFeats--;
|
||||
}
|
||||
@@ -1047,44 +1071,46 @@ json ResetFeats(json jHenchman, object oHenchman)
|
||||
}
|
||||
}
|
||||
// Give picked feats from package.
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 972, Checking for select feats.");
|
||||
nNumOfFeats = 1;
|
||||
if(GetHasFeat(FEAT_QUICK_TO_MASTER, oHenchman)) nNumOfFeats++;
|
||||
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));
|
||||
if(CanSelectFeat(jHenchman, oHenchman, 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, 1053, Adding character bonus feat: " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1082, Selecting character feat: " +
|
||||
Get2DAString("feat", "LABEL", nPackageFeat));
|
||||
nNumOfFeats--;
|
||||
}
|
||||
if(nNumOfFeats < 1) break;
|
||||
nPackageRow++;
|
||||
}
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1071, Adding feat list.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1089, Adding feat list.");
|
||||
jHenchman = GffReplaceList(jHenchman, "FeatList", jFeatList);
|
||||
return jHenchman;
|
||||
}
|
||||
json ResetSkills(json jHenchman, object oHenchman)
|
||||
json ResetSkills(json jHenchman, object oHenchman, int nLevel)
|
||||
{
|
||||
// We remake the Skill List if the character doesn't have a level list!
|
||||
int nClass = GetClassByPosition(1, oHenchman);
|
||||
int nSkillPoints, nIntMod = GetAbilityModifier(ABILITY_INTELLIGENCE, oHenchman);
|
||||
if(nIntMod > 0) nSkillPoints = nIntMod * 4;
|
||||
if(GetRacialType(oHenchman) == RACIAL_TYPE_HUMAN) nSkillPoints += 4;
|
||||
nSkillPoints += StringToInt(Get2DAString("classes", "SkillPointBase", nClass)) * 4;
|
||||
int nMaxRanks = 5;
|
||||
if(nIntMod > 0) nSkillPoints = nIntMod;
|
||||
if(GetRacialType(oHenchman) == RACIAL_TYPE_HUMAN) nSkillPoints += 1;
|
||||
nSkillPoints += StringToInt(Get2DAString("classes", "SkillPointBase", nClass));
|
||||
nSkillPoints = nSkillPoints * (nLevel + 3);
|
||||
int nMaxRanks = 3 + nLevel;
|
||||
json jSkillList = JsonArray();
|
||||
json jSkill;
|
||||
// Setup the Skill List.
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1087, Generating skill list.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1112, Generating skill list.");
|
||||
int nIndex, nSkillMaxRow = Get2DARowCount("skills");
|
||||
for(nIndex = 0; nIndex < nSkillMaxRow; nIndex++)
|
||||
{
|
||||
@@ -1094,7 +1120,7 @@ json ResetSkills(json jHenchman, object oHenchman)
|
||||
jSkillList = JsonArrayInsert(jSkillList, jSkill);
|
||||
}
|
||||
// Give skill points based on the package.
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1097, 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);
|
||||
@@ -1123,7 +1149,7 @@ json ResetSkills(json jHenchman, object oHenchman)
|
||||
{
|
||||
jSkill = GffReplaceByte(jSkill, "Rank", nCurrentRanks + nNewRanks);
|
||||
jSkillList = JsonArraySet(jSkillList, nPackageSkill, jSkill);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1126, Adding " + IntToString(nNewRanks) +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1145, Adding " + IntToString(nNewRanks) +
|
||||
" ranks to " + Get2DAString("skills", "Label", nPackageSkill) +
|
||||
" CrossClass: " + IntToString(bCrossClass));
|
||||
nSkillPoints -= nNewRanks;
|
||||
@@ -1135,9 +1161,9 @@ json ResetSkills(json jHenchman, object oHenchman)
|
||||
}
|
||||
json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
{
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1138, Checking for spells known.");
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1157, Checking for spells known.");
|
||||
int nClass = GetClassByPosition(1, oHenchman);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1140, 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!
|
||||
@@ -1179,7 +1205,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
{
|
||||
nSpellsKnown = StringToInt(Get2DAString(sSpellKnown2DAName, "SpellLevel" + sSpellLevel, nLevel));
|
||||
}
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1165, nSpellsKnown: " + IntToString(nSpellsKnown));
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1201, nSpellsKnown: " + IntToString(nSpellsKnown));
|
||||
jKnownList = JsonArray();
|
||||
nPackageRow = 0;
|
||||
while(nPackageRow < nPackageMaxRow && nSpellsKnown > 0)
|
||||
@@ -1201,7 +1227,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
if(JsonGetLength(jKnownList) == 0)
|
||||
{
|
||||
jClass = GffRemoveList(jClass, "KnownList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1187, Removing KnownList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1223, Removing KnownList" + sSpellLevel);
|
||||
}
|
||||
else if(JsonGetType(GffGetList(jClass, "KnownList" + sSpellLevel)) != JSON_TYPE_NULL)
|
||||
{
|
||||
@@ -1217,7 +1243,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
if(JsonGetType(jKnownList) != JSON_TYPE_NULL)
|
||||
{
|
||||
jClass = GffRemoveList(jClass, "KnownList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1203, Removing KnownList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1239, Removing KnownList" + sSpellLevel);
|
||||
}
|
||||
}
|
||||
if(bMemorizesSpells)
|
||||
@@ -1226,7 +1252,7 @@ json ResetSpellsKnown(json jClass, object oHenchman)
|
||||
if(JsonGetType(jMemorizedList) != JSON_TYPE_NULL)
|
||||
{
|
||||
jClass = GffRemoveList(jClass, "MemorizedList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1210, Removing MemorizedList" + sSpellLevel);
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1248, Removing MemorizedList" + sSpellLevel);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1237,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, 1223, Setting SpellsPerDay to " +
|
||||
WriteTimestampedLogEntry("pinc_henchmen, 1259, Setting SpellsPerDay to " +
|
||||
IntToString(nSpellsKnown));
|
||||
}
|
||||
nSpellLevel++;
|
||||
@@ -1248,11 +1274,12 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
{
|
||||
SetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE", TRUE);
|
||||
RemoveHenchman(oPC, oHenchman);
|
||||
ChangeToStandardFaction(oHenchman, STANDARD_FACTION_DEFENDER);
|
||||
json jHenchman = ObjectToJson(oHenchman, TRUE);
|
||||
json jClassList = GffGetList(jHenchman, "ClassList");
|
||||
json jClass = JsonArrayGet(jClassList, 0);
|
||||
// Set the Class list to the first class only and put at level 1.
|
||||
int nClass = JsonGetInt(JsonObjectGet(jClass, "Class"));
|
||||
int nClass = JsonGetInt(GffGetInt(jClass, "Class"));
|
||||
jClass = GffReplaceShort(jClass, "ClassLevel", 1);
|
||||
// Delete extra classes.
|
||||
int nClassIndex = JsonGetLength(jClassList) - 1;
|
||||
@@ -1260,15 +1287,10 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
{
|
||||
jClassList = JsonArrayDel(jClassList, nClassIndex--);
|
||||
}
|
||||
int nHitPoints = StringToInt(Get2DAString("classes", "HitDie", nClass));
|
||||
int nMod = JsonGetInt(GffGetByte(jHenchman, "Con"));
|
||||
if(nMod > 9) nHitPoints += (nMod - 10) / 2;
|
||||
else nHitPoints += (nMod - 11) / 2;
|
||||
jHenchman = GffReplaceShort(jHenchman, "CurrentHitPoints", nHitPoints);
|
||||
jHenchman = GffReplaceShort(jHenchman, "HitPoints", nHitPoints);
|
||||
jHenchman = GffReplaceShort(jHenchman, "MaxHitPoints", nHitPoints);
|
||||
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);
|
||||
string s2DA = Get2DAString("classes", "AttackBonusTable", nClass);
|
||||
int nAtk = StringToInt(Get2DAString(s2DA, "BAB", 0));
|
||||
jHenchman = GffReplaceByte(jHenchman, "BaseAttackBonus", nAtk);
|
||||
@@ -1282,7 +1304,7 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
json jLvlStatList = GffGetList(jHenchman, "LvlStatList");
|
||||
if(JsonGetType(jLvlStatList) != JSON_TYPE_NULL)
|
||||
{
|
||||
WriteTimestampedLogEntry("pinc_henchmen 1275, jLvlStatList: " + JsonDump(jLvlStatList, 4));
|
||||
//WriteTimestampedLogEntry("pinc_henchmen 1300, jLvlStatList: " + JsonDump(jLvlStatList, 4));
|
||||
int nLevel = 1, nLevelTrack = 1;
|
||||
int nAbilityStatIncrease, nAbility;
|
||||
string sAbility;
|
||||
@@ -1290,7 +1312,7 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
json jLevel = JsonArrayGet(jLvlStatList, nLevel);
|
||||
while(JsonGetType(jLevel) != JSON_TYPE_NULL)
|
||||
{
|
||||
WriteTimestampedLogEntry("inc_henchmen, 1297, 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)
|
||||
@@ -1316,12 +1338,21 @@ object ResetCharacter(object oPC, object oHenchman)
|
||||
jHenchman = GffRemoveList(jHenchman, "LvlStatList");
|
||||
}
|
||||
jHenchman = CreateLevelStatList(jHenchman, oHenchman, oPC, 1);
|
||||
jHenchman = ResetSkills(jHenchman, oHenchman);
|
||||
int nHitPoints = StringToInt(Get2DAString("classes", "HitDie", nClass));
|
||||
int nConstitution = JsonGetInt(GffGetByte(jHenchman, "Con"));
|
||||
int nRace = JsonGetInt(GffGetByte(jHenchman, "Race"));
|
||||
nConstitution += StringToInt(Get2DAString("racialtypes", "ConAdjust", nRace));
|
||||
if(nConstitution > 9) nHitPoints += (nConstitution - 10) / 2;
|
||||
else nHitPoints += (nConstitution - 11) / 2;
|
||||
jHenchman = GffReplaceShort(jHenchman, "CurrentHitPoints", nHitPoints);
|
||||
jHenchman = GffReplaceShort(jHenchman, "HitPoints", nHitPoints);
|
||||
jHenchman = GffReplaceShort(jHenchman, "MaxHitPoints", nHitPoints);
|
||||
jHenchman = ResetSkills(jHenchman, oHenchman, 1);
|
||||
jHenchman = ResetFeats(jHenchman, oHenchman);
|
||||
jClass = ResetSpellsKnown(jClass, oHenchman);
|
||||
jClassList = JsonArraySet(jClassList, 0, jClass);
|
||||
jHenchman = GffReplaceList(jHenchman, "ClassList", jClassList);
|
||||
//WriteTimestampedLogEntry("pinc_henchmen 1397, 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);
|
||||
@@ -1342,13 +1373,13 @@ void CreateCharacterEditGUIPanel(object oPC, object oHenchman)
|
||||
// Group 1 (Portrait)******************************************************* 151 / 73
|
||||
// Group 1 Row 1 *********************************************************** 350 / 91
|
||||
json jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer());
|
||||
jGroupRow = CreateTextEditBox (jGroupRow, "name_placeholder", "char_name", 15, FALSE, 140.0, 20.0);
|
||||
jGroupRow = CreateTextEditBox (jGroupRow, "name_placeholder", "char_name", 50, FALSE, 140.0, 20.0);
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
// Add the group row to the group column.
|
||||
json jGroupCol = JsonArrayInsert(JsonArray(), NuiRow(jGroupRow));
|
||||
// Group 1 Row 1 *********************************************************** 350 / 91
|
||||
jGroupRow = JsonArrayInsert(JsonArray(), NuiSpacer());
|
||||
jGroupRow = CreateTextEditBox (jGroupRow, "port_placeholder", "port_name", 15, FALSE, 140.0, 20.0, "port_tooltip");
|
||||
jGroupRow = CreateTextEditBox (jGroupRow, "port_placeholder", "port_name", 16, FALSE, 140.0, 20.0, "port_tooltip");
|
||||
jGroupRow = JsonArrayInsert(jGroupRow, NuiSpacer());
|
||||
// Add the group row to the group column.
|
||||
jGroupCol = JsonArrayInsert(jGroupCol, NuiRow(jGroupRow));
|
||||
@@ -1503,11 +1534,13 @@ void CreateCharacterEditGUIPanel(object oPC, object oHenchman)
|
||||
NuiSetBindWatch(oPC, nToken, "cmb_class_selected", bNoClass);
|
||||
NuiSetBind(oPC, nToken, "cmb_class_event", JsonBool(bNoClass));
|
||||
int nPackage = GetLocalInt(oHenchman, "PACKAGE_SELECTED_" + IntToString(nClassOption + 1));
|
||||
//SendMessageToPC(oPC, "nPackage: " + IntToString(nPackage) + " nSelection: " + IntToString(GetSelectionByPackage2DA(sClass, nPackage)));
|
||||
if(nPackage == 0)
|
||||
{
|
||||
nPackage = GetPackageBySelection2DA(sClass, 0);
|
||||
SetLocalInt(oHenchman, "PACKAGE_SELECTED_" + IntToString(nClassOption + 1), nPackage);
|
||||
}
|
||||
//SendMessageToPC(oPC, "nPackage: " + IntToString(nPackage) + " sClass: " + sClass);
|
||||
NuiSetBind(oPC, nToken, "cmb_package_selected", JsonInt(GetSelectionByPackage2DA(sClass, nPackage)));
|
||||
NuiSetBindWatch(oPC, nToken, "cmb_package_selected", bNoClass);
|
||||
NuiSetBind(oPC, nToken, "cmb_package_event", JsonBool(bNoClass));
|
||||
@@ -1538,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