2025/07/19 Update

Added PEPS.
Full compile.
This commit is contained in:
Jaysyn904 2025-07-19 12:24:29 -04:00
parent e518db42dc
commit 352e9f3ee2
168 changed files with 164196 additions and 1158 deletions

View File

@ -235,4 +235,14 @@ description = "PRC8 version of A Time For Heroes."
filter = "xchst_inc.nss"
[target.rules]
"*" = "src/module/$ext"
"*" = "src/module/$ext"
[target]
name = "pepshak"
file = "peps_prc8.hak"
description = "PEPS PRC hakpak for PRC8 version of A Time for Heroes."
[target.sources]
include = "src/hakpak/peps_prc8/**/*"
[target.rules]
"*" = "src/hakpak/peps_prc8/$ext"

1
pack_haks.cmd Normal file
View File

@ -0,0 +1 @@
nasher pack pepshak --verbose

View File

@ -0,0 +1,49 @@
2DA V2.0
Message_Type Text
0 AI_Message "Picking up too much junk? Adjust the loot filter."
1 AI_Message "Try the AI on your player for a different experience!"
2 AI_Message "Does your associates talk to much? Reduce their speech."
3 AI_Message "Modes will keep your character engaged in that task."
4 AI_Message "Give Thieves picks to your rogues, they will use them."
5 AI_Message "Want your associates using more magic? Up their magic level."
6 AI_Message "Using up spells too fast? Control what they can cast!"
7 AI_Message "You can adjust when associates heal in and out of combat."
8 AI_Message "Don't want to be a team player? Turn party healing off."
9 AI_Message "Need help picking up all that loot? Turn Auto looting on."
10 Widget_Message "Place your widgets then lock'em into place!"
11 Widget_Message "Like an associates settings? Copy them to other associates."
12 Widget_Message "Use action button to control your associates actions."
13 Widget_Message "'All' commands are good for getting control of the party."
14 Widget_Message "Normal mode clears any specific commands."
15 Widget_Message "Follow command makes them stop fighting and follow!"
16 Widget_Message "Have traps? You can make a skilled associate use them."
17 Widget_Message "Put the camera focus on an associate to get better control."
18 Widget_Message "Don't like your associates familiar? Change it!"
19 Widget_Message "Don't like your associates animal companion? Change it!"
20 General_Message "Right click on the widget portrait to open the AI menu."
21 General_Message "Give your associates magic items, they can use more now!"
22 General_Message "Use the boxes to the right to add commands to your widgets."
23 General_Message "Use the mouse wheel to change a button's [values]."
24 General_Message "Use the mouse wheel to change a button's [values]."
25 General_Message "Use the mouse wheel to change a button's [values]."
26 General_Message "Want a module supported? Ask on Discord or the Vault."
27 Rule_Message "Allow more henchman into your party, upto 12 can join!"
28 Rule_Message "Too many widgets? You can turn your associate widgets off!"
29 Rule_Message "Party too big and can't get down the hall? Use Ghost mode!"
30 Rule_Message "Is the game too easy? Goto Main Options and change the RULES!"
31 Rule_Message "Increase the difficulty, make monster attack weaker targets."
32 Rule_Message "Monsters too powerful? Turn on moral checks."
33 Rule_Message "Allow casters to prebuff for stronger opponents."
34 Rule_Message "Allow casters to presummon for more enemy support."
35 Rule_Message "Change up your opponents tactics. Turn on monster tactics."
36 Rule_Message "Allow enemies to have their familiars and animal companions."
37 Rule_Message "Make summons more powerful, stop unsummons on master's death!"
38 Rule_Message "Want a pile on? Increase the distance monsters can respond!"
39 Rule_Message "Monster's perception can be changed up or down!"
40 Rule_Message "Want to see a massacre! Set the enemy corpses to remain."
41 Rule_Message "Looking for variety? Turn on wandering to get a surprise!"
42 Rule_Message "Not hard enough? Up the number of monsters you fight!"
43 Rule_Message "Monsters just falling over? Increase their health!"
44 Widget_Message "Change your associates memorized spells to what you need!"
45 Widget_message "Control the spells your party uses by turning on the Quick use widget!"

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1206,6 +1206,7 @@ int GetIsDoubleSidedWeaponType(int iWeaponType)
return ( iWeaponType == BASE_ITEM_DIREMACE
|| iWeaponType == BASE_ITEM_DOUBLEAXE
|| iWeaponType == BASE_ITEM_TWOBLADEDSWORD
|| iWeaponType == BASE_ITEM_DOUBLE_SCIMITAR
);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -669,7 +669,7 @@
"Mod_Description": {
"type": "cexolocstring",
"value": {
"0": "A Time for Heroes\nv 1.03\nby Shawn Overcash\nbugfixes for version 1.03 by Stacey Keast\n\nA freeform hack&slash module that allows you to explore the world and make a name for yourself at your own leisure.\n\nSingle player only.\nFor characters level 1 to 40.\n\nNote: If you encounter any bugs or problems with the module, contact me through my profile (fsovercash) on NWVault.\n\nNote 2: Or contact me, Stacey Keast and I'll see if I can fix the bugs. (slikster on nwvault). Shawn seems to be on hiatus."
"0": "A Time for Heroes\nv 1.06prc8\nby Shawn Overcash\nbugfixes for version 1.03 by Stacey Keast\n\nA freeform hack&slash module that allows you to explore the world and make a name for yourself at your own leisure.\n\nSingle player only.\nFor characters level 1 to 40.\n\nNote: If you encounter any bugs or problems with the module, contact me through my profile (fsovercash) on NWVault.\n\nNote 2: Or contact me, Stacey Keast and I'll see if I can fix the bugs. (slikster on nwvault). Shawn seems to be on hiatus."
}
},
"Mod_DuskHour": {
@ -711,6 +711,13 @@
"Mod_HakList": {
"type": "list",
"value": [
{
"__struct_id": 8,
"Mod_Hak": {
"type": "cexostring",
"value": "peps_prc8"
}
},
{
"__struct_id": 8,
"Mod_Hak": {

View File

@ -0,0 +1,172 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_assoc_actions
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Conversation script that sets modes or allows oAssociate to do actions from a
conversation.
Param "sAction"
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
void main()
{
object oPC = GetPCSpeaker();
object oAssociate = OBJECT_SELF;
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
object oArea = GetArea(oAssociate);
string sAction = GetScriptParam("sAction");
// Scout ahead is done int 0e_ch_1_hb (heartbeat script).
if(sAction == "Scout")
{
ai_ClearCreatureActions();
ai_HaveCreatureSpeak(oAssociate, 4, ":29:35:46:");
ai_SetAIMode(oAssociate, AI_MODE_SCOUT_AHEAD, TRUE);
ai_ScoutAhead(oAssociate);
}
else if(sAction == "BasicTactics")
{
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "");
ai_SetAssociateAIScript(oAssociate, FALSE);
}
else if(sAction == "AmbushTactics")
{
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_ambusher");
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_ambusher");
}
else if(sAction == "DefensiveTactics")
{
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_defensive");
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_defensive");
}
else if(sAction == "RangedTactics")
{
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_ranged");
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_ranged");
}
else if(sAction == "Taunt")
{
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_taunter");
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_taunter");
}
else if(sAction == "CounterSpell")
{
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_cntrspell");
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_cntrspell");
}
else if(sAction == "PeaceTactics")
{
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_peaceful");
}
else if(sAction == "AttackTactics")
{
if(ai_GetAIMode(oAssociate, AI_MODE_CHECK_ATTACK))
{
ai_SetAIMode(oAssociate, AI_MODE_CHECK_ATTACK, FALSE);
}
else ai_SetAIMode(oAssociate, AI_MODE_CHECK_ATTACK, TRUE);
}
else if(sAction == "FollowCloser") ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType);
else if(sAction == "FollowFarther") ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType);
else if(sAction == "Pickup") ai_Loot(oPC, oAssociate, sAssociateType);
else if(sAction == "HealSelf") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 1);
else if(sAction == "HealAllies") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 2);
else if(sAction == "HealOutMinus") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType);
else if(sAction == "HealOutPlus") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType);
else if(sAction == "HealInMinus") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType);
else if(sAction == "HealInPlus") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType);
else if(sAction == "Traps") ai_Traps(oPC, oAssociate, sAssociateType);
else if(sAction == "Locks") ai_Locks(oPC, oAssociate, sAssociateType, 1);
else if(sAction == "Bash") ai_Locks(oPC, oAssociate, sAssociateType, 2);
else if(sAction == "Search") ai_Search(oPC, oAssociate, sAssociateType);
else if(sAction == "Stealth") ai_Stealth(oPC, oAssociate, sAssociateType);
else if(sAction == "NoMagic") ai_UseMagic(oPC, oAssociate, sAssociateType);
else if(sAction == "DefensiveCasting") ai_UseOffensiveMagic(oPC, oAssociate, TRUE, FALSE, sAssociateType);
else if(sAction == "OffensiveCasting") ai_UseOffensiveMagic(oPC, oAssociate, FALSE, TRUE, sAssociateType);
else if(sAction == "MagicMinus") ai_MagicIncrement(oPC, oAssociate, -1, sAssociateType);
else if(sAction == "MagicPlus") ai_MagicIncrement(oPC, oAssociate, 1, sAssociateType);
else if(sAction == "Speaking")
{
if(ai_GetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK))
{
ai_SetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK, FALSE);
}
else ai_SetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK, TRUE);
}
else if(sAction == "Ranged")
{
if(ai_GetAIMode(oAssociate, AI_MODE_STOP_RANGED))
{
ai_SetAIMode(oAssociate, AI_MODE_STOP_RANGED, FALSE);
}
else ai_SetAIMode(oAssociate, AI_MODE_STOP_RANGED, TRUE);
}
else if(sAction == "AtkAssociates")
{
if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES))
{
ai_SetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES, FALSE);
}
else ai_SetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES, TRUE);
}
else if(sAction == "BuffFirst")
{
if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER))
{
ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER, FALSE);
}
else ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER, TRUE);
}
else if(sAction == "RestBuffing")
{
if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST))
{
ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST, FALSE);
}
else ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST, TRUE);
}
else if(sAction == "Dispel")
{
if(ai_GetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL))
{
ai_SetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL, FALSE);
}
else ai_SetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL, TRUE);
}
else if(sAction == "MagicItems")
{
if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS))
{
ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS, FALSE);
}
else ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS, TRUE);
}
else if(sAction == "Identify")
{
ai_IdentifyAllVsKnowledge(oAssociate, oPC, oPC);
return;
}
else if(sAction == "GiveUnIdentifiedItems")
{
ai_ClearCreatureActions();
object oItem = GetFirstItemInInventory(oAssociate);
while(oItem != OBJECT_INVALID)
{
if(!GetIdentified(oItem)) ActionGiveItem(oItem, oPC);
oItem = GetNextItemInInventory(oAssociate);
}
return;
}
else if(sAction == "GiveMagicItems")
{
ai_ClearCreatureActions();
itemproperty ipItemProp;
object oItem = GetFirstItemInInventory(oAssociate);
while(oItem != OBJECT_INVALID)
{
ipItemProp = GetFirstItemProperty(oItem);
if(GetIsItemPropertyValid(ipItemProp)) ActionGiveItem(oItem, oPC);
oItem = GetNextItemInInventory(oAssociate);
}
return;
}
aiSaveAssociateModesToDb(oPC, oAssociate);
}

View File

@ -0,0 +1,18 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
Script Name: 0c_cast_polymorp
Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
Conversation script to have a henchman cast a polymorph spell.
int nSpell is the spell to cast.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_items"
void main()
{
object oHenchman = OBJECT_SELF;
int nSpell = StringToInt (GetScriptParam ("nSpell"));
// Save the original form so we can check when we turn back (Add 1 so we don't save a 0!).
SetLocalInt (oHenchman, AI_NORMAL_FORM, GetAppearanceType (oHenchman) + 1);
SetLocalString (oHenchman, AI_COMBAT_SCRIPT, "ai_a_polymorphed");
ActionCastSpellAtObject (nSpell, oHenchman, 255, TRUE);
}

View File

@ -0,0 +1,15 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_fire_henchmen
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Action taken script to fire/remove henchman for higher.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
void main()
{
object oHenchman = OBJECT_SELF;
ai_ClearCreatureActions();
ai_FireHenchman (GetPCSpeaker(), oHenchman);
PlayVoiceChat (VOICE_CHAT_GOODBYE, oHenchman);
}

View File

@ -0,0 +1,22 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_get_convo
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Action taken script that leaves the current conversation and starts a new
conversation with oCreature using the linked conversation instead of the
ai_Henchman conversation.
Allows use of ai_conversation for henchman in other modules.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void BeginOriginalHenchmanConversation(string sDialog, object oPC)
{
BeginConversation(sDialog, oPC);
}
void main()
{
ai_ClearCreatureActions();
// Need to check special dialogs for HOTU henchman.
string sDialog = GetDialogFileToUse(GetLastSpeaker());
DelayCommand(0.0, BeginOriginalHenchmanConversation(sDialog, GetPCSpeaker()));
}

View File

@ -0,0 +1,25 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_get_henchman
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Action taken script that adds oCreature to oPC's party as a henchman
while giving a random message.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
void main()
{
object oCreature = OBJECT_SELF;
object oPC = GetPCSpeaker();
AddHenchman(oPC, oCreature);
int nVoice;
switch(d4())
{
case 1: nVoice = VOICE_CHAT_CANDO; break;
case 2: nVoice = VOICE_CHAT_CHEER; break;
case 3: nVoice = VOICE_CHAT_GOODIDEA; break;
case 4: nVoice = VOICE_CHAT_LAUGH; break;
}
PlayVoiceChat(nVoice, oCreature);
}

View File

@ -0,0 +1,12 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_cast_spell
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Action taken script that sets the specified spell to be cast.
Param
nSpell - the spell to cast.
*///////////////////////////////////////////////////////////////////////////////
void main()
{
SetLocalInt (OBJECT_SELF, "0_SPELL_TO_CAST", StringToInt (GetScriptParam ("nSpell")));
}

View File

@ -0,0 +1,81 @@
/*///////////////////////////////////////////////////////////////////////////////
Script: 0c_henchmenspell
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Action script to cast a specific spell for a henchman.
Script Param
nTarget (INT) : 0 = ALL, 1 PC, 2 Caster, 3-6 = oPC's Henchman, 7 = PC's Familiar
8 = PC's Animal Companion, 9 = PC's Summon.
nBuffType = 1 all 2 short 3 long, 4 healing, 5 lay on hands.
If nBuffType is 0 then it will cast a specific spell from
Variable "0_SPELL_TO_CAST". Use script: 0c_h_spell_cast spell to set the spell.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
float ai_UseLayOnHands(object oTarget, object oPC, float fDelay, object oCaster);
void main()
{
object oTarget, oPC = GetPCSpeaker();
object oCreature = OBJECT_SELF;
float fDelay;
int nTarget = StringToInt(GetScriptParam("nTarget"));
int nBuffType = StringToInt(GetScriptParam("nBuffType"));
// Cast a group of buff spells based on nBuffType and nTarget or a single spell.
if(nBuffType < 4)
{
// Cast a specific spell.
if(nBuffType == 0)
{
int nSpell = GetLocalInt(oCreature, "0_SPELL_TO_CAST");
// These are buff spells so Acid fog (index 0) is not a valid spell.
if(nSpell > 0)
{
ai_ClearCreatureActions();
object oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget));
if(oTarget != OBJECT_INVALID && ai_CheckAndCastSpell(oCreature, nSpell, 0, 0.0f, oTarget, oPC))
{
DeleteLocalInt(oCreature, "0_SPELL_TO_CAST");
}
else
{
if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_CANTDO, oCreature);
string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
ai_SendMessages("I cannot cast " + sSpellName + ".", AI_COLOR_RED, oPC);
}
}
}
// Cast a creatures buff spells on nTarget.
else ai_CastBuffs(oCreature, nBuffType, nTarget, oPC);
}
// Cast Healing spells.
else if(nBuffType == 4)
{
ai_SetupAllyTargets(oCreature, oPC);
oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget));
ai_TryHealing(oCreature, oTarget);
}
// Use lay on hands.
else if(nBuffType == 5)
{
ai_SetupAllyTargets(oCreature, oPC);
oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget));
ai_UseLayOnHands(oTarget, oPC, 0.0f, oCreature);
}
else if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_CUSS, oCreature);
}
float ai_UseLayOnHands(object oTarget, object oPC, float fDelay, object oCreature)
{
int nHpLost = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget);
if(!nHpLost)
{
if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_CANTDO, oCreature);
ai_SendMessages(GetName(oTarget) + " does not need healed.", AI_COLOR_RED, oPC);
}
else
{
ai_SendMessages(GetName(oCreature) + " is laying hands on " + GetName(oTarget), AI_COLOR_GREEN, oPC);
ActionUseFeat(FEAT_LAY_ON_HANDS, oTarget);
fDelay += 6.0f;
}
return fDelay;
}

View File

@ -0,0 +1,16 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_a_magic_m
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see if the henchmen has a specific
associate magic mode.
Param:
nMode - The mode to check.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
object oHenchman = OBJECT_SELF;
int nMode = StringToInt(GetScriptParam("nMode"));
return ai_GetMagicMode (oHenchman, nMode);
}

View File

@ -0,0 +1,132 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_ass_convo
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that has the henchman tell the player what options
have been selected.
sOption will decide what the henchman says.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
object oPC = GetPCSpeaker();
object oAssociate = OBJECT_SELF;
string sParam = GetScriptParam("sOption");
if(sParam == "BaseMode")
{
string sBaseMode = "I'm ready to attack.";
string sVolume = " While shouting when I see things.";
// Lets get which base mode the henchman is in.
if(ai_GetAIMode(oAssociate, AI_MODE_STAND_GROUND)) sBaseMode = "I'm holding here.";
else if(ai_GetAIMode(oAssociate, AI_MODE_DEFEND_MASTER)) sBaseMode = "I'm defending you.";
else if(ai_GetAIMode(oAssociate, AI_MODE_FOLLOW)) sBaseMode = "I'm following you.";
if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_peaceful") sBaseMode = "I will not fight the enemy!";
if(ai_GetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK)) sVolume = " While not speaking unless spoken to.";
SetCustomToken(AI_BASE_CUSTOM_TOKEN, sBaseMode + sVolume);
}
else if(sParam == "CombatTactics")
{
string sRangedUse = "", sCombatTactic = "I'm using my best judgement in combat ";
string sAtkAssociates = "";
string sTargets = "against all enemies and ";
// Lets get which base mode the henchman is in.
if(ai_GetAIMode(oAssociate, AI_MODE_CHECK_ATTACK)) sTargets = "against enemies I can handle and ";
if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_ambusher") sCombatTactic = "I'm using ambush tactics ";
else if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_defensive") sCombatTactic = "I'm using defensive tactics ";
else if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_taunter") sCombatTactic = "I'm ready to taunt ";
else if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_cntrspell") sCombatTactic = "I'm ready to counter spell ";
if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_peaceful")
{
sCombatTactic = "I will not fight the enemy!";
sTargets = "";
}
else
{
if(ai_GetAIMode(oAssociate, AI_MODE_STOP_RANGED)) sRangedUse = "will not use a ranged weapon.";
else sRangedUse = "will use a ranged weapon.";
if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES)) sAtkAssociates = " I will also ignore familiars, companions, and summons.";
else sAtkAssociates = " I will also attack familiars, companions, and summons.";
}
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 1, sCombatTactic + sTargets + sRangedUse + sAtkAssociates);
}
else if(sParam == "Plans")
{
float fFollowRange = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE);
string sFollowRange = FloatToString(fFollowRange, 0, 0);
string sDistance = "I'm following from " + sFollowRange + " meters away while";
string sStealth, sSearch, sPickup;
if(ai_GetAIMode(oAssociate, AI_MODE_PICKUP_ITEMS)) sPickup = " picking up items";
else sPickup = " not picking up any items";
if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_STEALTH)) sStealth = " in stealth";
else sStealth = "";
if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_SEARCH)) sSearch = " and searching";
else sSearch = "";
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 2, sDistance + sPickup + sStealth + sSearch + ".");
}
else if(sParam == "Healing")
{
string sHealingIn = IntToString(GetLocalInt(oAssociate, AI_HEAL_IN_COMBAT_LIMIT)) + "%";
string sHealingOut = IntToString(GetLocalInt(oAssociate, AI_HEAL_OUT_OF_COMBAT_LIMIT)) + "%";
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 5, "I'm healing our allies if they go below " +
sHealingIn + " health in combat and " + sHealingOut + " out of combat.");
}
else if(sParam == "Spells")
{
string sCastingLevel = "[" + IntToString(GetLocalInt(oAssociate, AI_DIFFICULTY_ADJUSTMENT)) + "] ";
string sCasting = "I'm casting";
string sType = " spells I choose.";
string sBuff = " I'll also targeting anyone that needs it ";
string sDispel = "while using Dispel spells.";
string sMagicItems = " Lastly I'll use any magic items I have.";
if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER)) sBuff = " Ofcourse I'll target you first ";
if(ai_GetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL)) sDispel = "while not using Dispel spells.";
if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_cntrspell")
{
sCasting = "I'm ready to counter spell our enemies.";
sType = "";
sBuff = "";
sDispel = "";
}
if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC))
{
sCasting = "I'm not use any magic.";
sType = "";
sBuff = "";
sDispel = "";
}
else if(ai_GetMagicMode(oAssociate, AI_MAGIC_DEFENSIVE_CASTING)) sType = " defensive spells only.";
else if(ai_GetMagicMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING))
{
sType = " offensive spells only.";
sBuff = "";
}
else if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS)) sMagicItems = " Finally I'll not use magic items.";
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 5, sCastingLevel + sCasting + sType + sBuff + sDispel+ sMagicItems);
}
else if(sParam == "Objects")
{
int bTraps = ai_GetAIMode(oAssociate, AI_MODE_DISARM_TRAPS);
int bLocks = ai_GetAIMode(oAssociate, AI_MODE_PICK_LOCKS);
int bBash = ai_GetAIMode(oAssociate, AI_MODE_BASH_LOCKS);
string sText = "I'm going to ignore all traps and locks.";
if(bTraps && bLocks && bBash)
{
sText = "I'm disarming all the traps and am either picking or bashing any of the locks we find.";
}
else if(bTraps && bLocks) sText = "I'm going to disarm all the traps and I'll pick all the locks we encounter.";
else if(bTraps && bBash) sText = "I shall disarm all the traps and will bash any locks we come across.";
else if(bTraps) sText = "I will disarm all the traps I can but will leave any locks for you to deal with.";
else if(bLocks && bBash) sText = "I will leave the traps for you but will either pick or bash any locks we see.";
else if(bLocks) sText = "I'll keep my distance from any traps we see, but will pick the locks found.";
else if(bBash) sText = "I'll let you mess with the traps, but I'll bash any locks that are out there.";
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 3, sText);
}
else if(sParam == "RestBuffing")
{
string sRestBuffing = "";
if(!ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST)) sRestBuffing = "not ";
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 10, "After we rest I am " + sRestBuffing + "casting my long buff spells on us.");
}
return TRUE;
}

View File

@ -0,0 +1,22 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_assoc_mode
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see if the henchmen has a specific
associate mode.
Param:
nMode - The mode to check.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
object oHenchman = OBJECT_SELF;
int nMode = StringToInt(GetScriptParam("nMode"));
// This conversation line turns off picking up any items.
if (nMode == -1)
{
if(ai_SetAIMode (oHenchman, AI_MODE_PICKUP_ITEMS)) return TRUE;
return FALSE;
}
return ai_GetAIMode (oHenchman, nMode);
}

View File

@ -0,0 +1,17 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_cntrspell
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that returns TRUE the server allows a henchman to
use counterspell and if they don't have the counterspell ai script set.
Param:
sAIScript - The special combat script to check.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
object oHenchman = OBJECT_SELF;
return (AI_COUNTERSPELLING_ON &&
ai_CheckClassType(oHenchman, AI_CLASS_TYPE_CASTER) &&
GetLocalString(oHenchman, AI_COMBAT_SCRIPT) != "ai_a_cntrspell");
}

View File

@ -0,0 +1,16 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_com_script
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that returns TRUE the caller does have an ai combat
script set to sAIScript.
Param:
sAIScript - The special combat script to check.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
string sAIScript = GetScriptParam("sAIScript");
string sAICombatScript = GetLocalString (OBJECT_SELF, AI_COMBAT_SCRIPT);
return (sAIScript == sAICombatScript);
}

View File

@ -0,0 +1,21 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_if_convo
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that check if oCreature has a linked conversation.
Only checks for Henchman.
Allows use of ai_conversation for henchman in other modules.
*///////////////////////////////////////////////////////////////////////////////
#include "nw_inc_gff"
#include "0i_messages"
int StartingConditional()
{
object oHenchman = OBJECT_SELF;
if(GetAssociateType(oHenchman) == ASSOCIATE_TYPE_HENCHMAN)
{
json jHenchman = ObjectToJson(oHenchman);
string sConversation = JsonGetString(GffGetResRef(jHenchman, "Conversation"));
if(sConversation != "") return TRUE;
}
return FALSE;
}

View File

@ -0,0 +1,18 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_has_assoc
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see if caller has the specified feat
to summon either a companion or a familiar and they are not summoned.
Param
sAssociate - "Familiar" or "Companion"
*///////////////////////////////////////////////////////////////////////////////
int StartingConditional()
{
object oHenchman = OBJECT_SELF;
string sAssociate = GetScriptParam("sAssociate");
if(sAssociate == "Familiar" && GetHasFeat(FEAT_SUMMON_FAMILIAR, oHenchman) &&
GetAssociate(ASSOCIATE_TYPE_FAMILIAR) == OBJECT_INVALID) return TRUE;
return (sAssociate == "Companion" && GetHasFeat(FEAT_ANIMAL_COMPANION, oHenchman) &&
GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION) == OBJECT_INVALID);
}

View File

@ -0,0 +1,28 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_has_class
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see if conversation owner has a
specified class. Multiple classes maybe selected.
Param
nClass# - the class to look for use nClass1, nClass2, nClass3 for each one to check.
*///////////////////////////////////////////////////////////////////////////////
int StartingConditional()
{
object oHenchman = OBJECT_SELF;
int nCntr = 1;
int nClass;
string sClass;
while(nCntr < 10)
{
sClass = GetScriptParam("nClass" + IntToString(nCntr));
if(sClass != "")
{
nClass = StringToInt(sClass);
if(GetLevelByClass(nClass, oHenchman)) return TRUE;
nCntr++;
}
else break;
}
return FALSE;
}

View File

@ -0,0 +1,22 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_has_feat
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see if they have a specific feat.
Param:
sTarget - either "OBJECT_SELF", or "PCSpeaker", blanks defaults to "PCSpeaker"
nFeat - the feat number from Feats.2da
bNot - if 1 TRUE then this returns true for the target not having the feat.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_main"
int StartingConditional()
{
string sTarget = GetScriptParam("sTarget");
int nFeat = StringToInt(GetScriptParam("nFeat"));
int bNot = StringToInt(GetScriptParam("bNot"));
object oCreature;
if(sTarget == "OBJECT_SELF") oCreature = OBJECT_SELF;
else if(sTarget == "" || sTarget == "PCSpeaker") oCreature = GetPCSpeaker();
if(bNot) return !GetHasFeat(nFeat, oCreature);
return (GetHasFeat(nFeat ,oCreature) || ai_GetIsDungeonMaster(oCreature));
}

View File

@ -0,0 +1,26 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_has_spell
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see if caster can cast the specified spell.
Param
nSpell# - the spell to look for nSpell1, sSpell2, nSpell3 for each spell to check.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_spells"
int StartingConditional()
{
object oCaster = OBJECT_SELF;
int nCnt = 1;
int nSpell;
string sSpell;
while(nCnt < 20)
{
sSpell = GetScriptParam("nSpell" + IntToString(nCnt));
if(sSpell == "") return FALSE;
nSpell = StringToInt(sSpell);
if(GetHasSpell(nSpell, oCaster)) return TRUE;
//else if(ai_GetKnownSpell(oCaster, nSpell)) return TRUE;
nCnt++;
}
return FALSE;
}

View File

@ -0,0 +1,12 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_hen_leave
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that check if allowing the player to remove a henchman
is activated on this server.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
return AI_REMOVE_HENCHMAN_ON;
}

View File

@ -0,0 +1,17 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_identify
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see if the henchmen has a better lore
skill than the speaker.
Also checks AI_IDENTIFY_ON to see if the server wants them to help.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
object oHenchman = OBJECT_SELF;
if (!AI_IDENTIFY_ON && !ai_CanISpeak (oHenchman)) return FALSE;
int nHenchmanLore = GetSkillRank(SKILL_LORE, oHenchman);
int nMasterLore = GetSkillRank(SKILL_LORE, GetMaster(oHenchman));
return (nHenchmanLore > nMasterLore);
}

View File

@ -0,0 +1,11 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_not_master
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks if the speaker is the master of this
henchman.
*///////////////////////////////////////////////////////////////////////////////
int StartingConditional()
{
return !GetIsObjectValid(GetMaster());
}

View File

@ -0,0 +1,13 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_open_equip
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks if opening a henchmans inventory
is activated on this server.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
if(GetAssociateType(OBJECT_SELF) != ASSOCIATE_TYPE_HENCHMAN) return FALSE;
return AI_OPEN_INVENTORY;
}

View File

@ -0,0 +1,12 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_pickuploot
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that check if having associates picking up loot is
activated on this server.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
return AI_PICKUP_LOOT;
}

View File

@ -0,0 +1,11 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_polymorph
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see if the caller is polymorphed.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
if (GetLocalInt(OBJECT_SELF, AI_NORMAL_FORM) != 0) return TRUE;
return FALSE;
}

View File

@ -0,0 +1,11 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_scout
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that check if scouting is activated on this server.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
return AI_SCOUT_AHEAD_ON;
}

View File

@ -0,0 +1,18 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_SkillRank
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see if the caller's skill ranks
are above or equal to the param value.
Param:
nSkill - the skill number for the skill. See skills.2da.
nRank - the rank required.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_main"
int StartingConditional()
{
string sSkill = GetScriptParam("nSkill");
if(sSkill == "") return FALSE;
int nRank = StringToInt(GetScriptParam("nRank"));
return (GetSkillRank(StringToInt(sSkill)) >= nRank);
}

View File

@ -0,0 +1,15 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_taunt
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that returns TRUE the server allows a henchman to
taunt and if they have the don't have the taunt ai script set.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
object oHenchman = OBJECT_SELF;
return (AI_TAUNTING_ON &&
GetSkillRank(SKILL_TAUNT, oHenchman) > ai_GetCharacterLevels(oHenchman) &&
GetLocalString(oHenchman, AI_COMBAT_SCRIPT) != "ai_a_taunter");
}

View File

@ -0,0 +1,19 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
Script Name: 0c_cast_polymorp
Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
Conversation script to setup the tokens for the henchman in the speakers party
except for who they are talking to.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
object oSpeaker = OBJECT_SELF;
object oPC = GetPCSpeaker();
int nCntr = 1;
object oHenchman = GetHenchman(oPC, nCntr);
while(oHenchman != OBJECT_INVALID)
{
if(oHenchman != oSpeaker) SetCustomToken(77100 + nCntr, GetName(oHenchman));
oHenchman = GetHenchman(oPC, ++nCntr);
}
}

View File

@ -0,0 +1,27 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_no_com_script
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that returns TRUE the caller does not have an ai combat
script set to sAIScript.
if sAIScript is blank then if its equal to all of them.
Param: sAIScripts:"ai_a_ambusher", "ai_a_defensive", "ai_a_taunter", "ai_coward".
sAIScript - The special combat script to check.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
string sAIScript = GetScriptParam("sAIScript");
string sAICombatScript = GetLocalString (OBJECT_SELF, AI_COMBAT_SCRIPT);
// This is the value for do your own thing in combat!
if (sAIScript == "")
{
return (sAICombatScript == "ai_a_ambusher" ||
sAICombatScript == "ai_a_defensive" ||
sAICombatScript == "ai_a_ranged" ||
sAICombatScript == "ai_a_taunter" ||
sAICombatScript == "ai_a_cntrspell" ||
sAICombatScript == "ai_a_peaceful");
}
return (sAIScript != sAICombatScript);
}

View File

@ -0,0 +1,14 @@
/*//////////////////////////////////////////////////////////////////////////////
Script:0c_remove_effect
Programmer:Philos
////////////////////////////////////////////////////////////////////////////////
Actions Taken script that removes an effect from OBJECT_SELF.
Param: nEffect - the EFFECT_TYPE_* number to remove.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_spells"
void main ()
{
int nEffect = StringToInt (GetScriptParam ("nEffectType"));
ai_RemoveASpecificEffect (OBJECT_SELF, nEffect);
}

View File

@ -0,0 +1,17 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
Script Name: 0c_summon_assoc
Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
Conversation script to have the caller summon either an animal companion or
familiar associate.
Param
sAssociate - which associate to summon.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
void main()
{
string sAssociate = GetScriptParam ("sAssociate");
if (sAssociate == "Familiar") SummonFamiliar ();
else if (sAssociate == "Companion") SummonAnimalCompanion ();
}

View File

@ -0,0 +1,15 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
Script Name: 0c_summon_assoc
Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
Conversation script to have the caller use nFeat from the feat.2da.
Param
nFeat - Feat number from the feat.2da.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
void main()
{
int nFeat = StringToInt (GetScriptParam ("nFeat"));
ActionUseFeat(nFeat, OBJECT_SELF);
}

View File

@ -0,0 +1,16 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_c2_1_hb
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Monster OnHeartbeat script;
This will usually fire every 6 seconds (1 game round).
I am reverting the AI script back to the games default scripts for efficiency.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_module"
void main()
{
SetLocalInt(OBJECT_SELF, AI_ONSPAWN_EVENT, TRUE);
ai_ChangeEventScriptsForMonster(OBJECT_SELF);
ExecuteScript("nw_c2_default1");
}

View File

@ -0,0 +1,32 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_c2_7_ondeath
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Monster OnDeath script;
This fires when the creature dies.
*////////////////////////////////////////////////////////////////////////////////
#include "0i_module"
void main()
{
object oCreature = OBJECT_SELF;
// Added code to allow for permanent associates in the battle!
object oModule = GetModule();
if(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))
{
object oAssociate;
int nIndex;
for(nIndex = 1; nIndex < 5; nIndex++)
{
oAssociate = GetAssociate(nIndex, oCreature);
if(oAssociate != OBJECT_INVALID)
{
SetIsDestroyable(FALSE, FALSE, FALSE);
DelayCommand(0.1, ChangeToStandardFaction(oAssociate, STANDARD_FACTION_HOSTILE));
}
}
}
if(GetLocalInt(oModule, AI_RULE_CORPSES_STAY)) SetIsDestroyable(FALSE, FALSE, TRUE);
ai_ClearCombatState(oCreature);
ExecuteScript(GetLocalString(oCreature, "AI_ON_DEATH"));
}

View File

@ -0,0 +1,14 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_ch_1_hb
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Associate(Summons, Familiar, Companion) OnHeart beat script when out of combat;
This will usually fire every 6 seconds (1 game round).
*///////////////////////////////////////////////////////////////////////////////
#include "0i_module"
void main()
{
SetLocalInt(OBJECT_SELF, AI_ONSPAWN_EVENT, TRUE);
ai_ChangeEventScriptsForAssociate(OBJECT_SELF);
ExecuteScript("nw_ch_ac1");
}

View File

@ -0,0 +1,41 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_ch_7_ondeath
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Associate OnSpawn script;
This fires when an associate dies.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_module"
void main()
{
object oCreature = OBJECT_SELF;
// Added code to allow for permanent associates in the battle!
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "13", GetName(oCreature) + " has died!" +
" AI_RULE_PERM_ASSOC: " + IntToString(GetLocalInt(GetModule(), AI_RULE_PERM_ASSOC)));
object oModule = GetModule();
if(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))
{
object oAssociate;
int nIndex;
for(nIndex = 2; nIndex < 5; nIndex++)
{
oAssociate = GetAssociate(nIndex, oCreature);
if(oAssociate != OBJECT_INVALID)
{
SetIsDestroyable(FALSE, FALSE, FALSE);
ChangeFaction(oAssociate, oCreature);
}
}
}
// Remove the widget!
object oPC = GetMaster(oCreature);
if(oPC != OBJECT_INVALID)
{
NuiDestroy(oPC, NuiFindWindow(oPC, ai_GetAssociateType(oPC, oCreature) + AI_WIDGET_NUI));
DelayCommand(0.5, ai_CheckXPPartyScale(oCreature));
DelayCommand(2.0, ai_ClearCreatureActions(TRUE));
}
DelayCommand(2.0, ai_ClearCombatState(oCreature));
ExecuteScript(GetLocalString(oCreature, "AI_ON_DEATH"));
}

View File

@ -0,0 +1,22 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_do_combat_rnd
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Used to execute a combat round just after the current action is over.
Note: Do not use with an attack action since it will continue until
the attacked enemy is dead. We end attack actions with a ClearAllActions
command and would also end this one so it will not work with attack actions.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
void main()
{
object oCreature = OBJECT_SELF;
if(AI_DEBUG) ai_Debug("0e_do_combat_rnd", "14", GetName(oCreature) + " is calculating a new round." +
"nAction: " + IntToString(GetCurrentAction(oCreature)));
if(ai_GetIsInCombat(oCreature))
{
if(GetAssociateType(oCreature) == ASSOCIATE_TYPE_NONE &&
!ai_GetIsCharacter(oCreature)) ai_DoMonsterCombatRound(oCreature);
else if(ai_CanIAttack(oCreature)) ai_DoAssociateCombatRound(oCreature);
}
}

View File

@ -0,0 +1,60 @@
/*//////////////////////////////////////////////////////////////////////////////
Script Name: 0e_gui_events
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
OnPlayerGUIEvent event script
Used to allow PEPS to gain control of specific GUI events.
/*//////////////////////////////////////////////////////////////////////////////
#include "0i_gui_events"
#include "0i_menus"
void main()
{
object oPC = GetLastGuiEventPlayer();
int nEventType = GetLastGuiEventType();
int nEventInt = GetLastGuiEventInteger();
//object oEventObject = GetLastGuiEventObject();
switch(nEventType)
{
case GUIEVENT_EFFECTICON_CLICK:
{
if(ai_GetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT))
{
ai_CreateEffectChatReport(oPC, nEventInt);
return;
}
int nToken = NuiFindWindow(oPC, AI_EFFECT_ICON_NUI);
json jData;
if(nToken)
{
jData = NuiGetUserData(oPC, nToken);
int nOldEffectIcon = JsonGetInt(JsonArrayGet(jData, 1));
DelayCommand(0.0, NuiDestroy(oPC, nToken));
if(nOldEffectIcon == nEventInt) return;
}
ai_CreateEffectIconMenu(oPC, nEventInt);
}
case GUIEVENT_PARTYBAR_PORTRAIT_CLICK:
{
object oAssociate = GetLastGuiEventObject();
if(GetMaster(oAssociate) == oPC)
{
// If all the Command buttons are blocked then don't load the menu.
if(GetLocalInt(GetModule(), sDMWidgetAccessVarname) != 7340028)
{
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
if(IsWindowClosed(oPC, sAssociateType + AI_COMMAND_NUI))
{
ai_CreateAssociateCommandNUI(oPC, oAssociate);
}
IsWindowClosed(oPC, sAssociateType + AI_NUI);
IsWindowClosed(oPC, sAssociateType + AI_LOOTFILTER_NUI);
IsWindowClosed(oPC, sAssociateType + AI_COPY_NUI);
IsWindowClosed(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
IsWindowClosed(oPC, sAssociateType + AI_SPELL_MEMORIZE_NUI);
IsWindowClosed(oPC, sAssociateType + AI_SPELL_KNOWN_NUI);
}
}
}
}
}

View File

@ -0,0 +1,46 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_m1_3_endround
Original Script: m1_combanter_3
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Monster OnCombatRoundEnd event script used in the original campaign
for monsters that may do a one liner during combat;
Fires at the end of each combat round (6 seconds).
This will fire as long as oCreature is in combat (GetIsInCombat()).
This event starts counting once a combat action is started.
Every time a spell is cast it will queue another end combat round so haste with
two spells cast will fire this twice in one round.
It will also fire at the end of a hostile effect that stops actions i.e Stunned, Knockdown etc.
Action modes are also cleared prior to this event executing!
GetAttemptedAttackTarget() & GetAttemptedSpellTarget() also get cleared prior to this event.
This event can be canceled with ClearAllActions(TRUE) and SurrenderToEnemies.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
if(AI_DEBUG) ai_Debug("0e_m1_3_endround", "23", GetName(oCreature) + " ends combat round.");
// Action modes get cleared prior to each OnCombatRoundEnd!
// We do this to keep the action mode going.
int nActionMode = GetLocalInt(oCreature, AI_CURRENT_ACTION_MODE);
if(nActionMode > 0)
{
SetActionMode(oCreature, nActionMode, TRUE);
// We don't want to use up all of the Dwarven Defenders uses!
if(nActionMode == 12) IncrementRemainingFeatUses(oCreature, FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE);
}
if (ai_GetIsBusy(oCreature) || ai_Disabled(oCreature)) return;
if(Random(4) == 0) SpeakOneLinerConversation();
if(ai_GetIsInCombat(oCreature)) ai_DoMonsterCombatRound(oCreature);
ai_SpellConcentrationCheck(oCreature);
if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) ai_DetermineSpecialBehavior(oCreature);
if(GetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT))
{
SignalEvent(OBJECT_SELF, EventUserDefined(1003));
}
}

1975
src/module/nss/0e_nui.nss Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,700 @@
/*//////////////////////////////////////////////////////////////////////////////
Script Name: 0e_nui_dm
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Menu event script
sEvent: close, click, mousedown, mouseup, watch (if bindwatch is set).
/*//////////////////////////////////////////////////////////////////////////////
#include "0i_menus_dm"
void ai_SetDMWidgetButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
void ai_SetDMWAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
void ai_SetDMAIAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
void ai_SetDMAIAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
void ai_RulePercDistInc(object oDM, object oModule, int nIncrement, int nToken);
// Adds a spell to a json AI restricted spell list then returns jRules.
// bRestrict = TRUE will add to the list FALSE will remove it from the list.
json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE);
// Adds a selected creature to the group.
void ai_SelectToGroup(object oDM, string sElem);
// Does a selected action for nGroup.
void ai_DMSelectAction(object oDM, string sElem);
// Changes if the group will run (nSpeed: 1) or walk (nSpeed: 0).
void ai_DMChangeMoveSpeed(object oDM, string sElem, int nSpeed);
void main()
{
object oDM = NuiGetEventPlayer();
int nToken = NuiGetEventWindow();
string sEvent = NuiGetEventType();
string sElem = NuiGetEventElement();
int nIndex = NuiGetEventArrayIndex();
string sWndId = NuiGetWindowId(oDM, nToken);
//if(AI_DEBUG) ai_Debug ("0e_nui", "58", "sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem +
// " nToken: " + IntToString(nToken) + " oPC: " + GetName(oPC));
//WriteTimestampedLogEntry("0e_nui, 58, sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem +
// " nToken: " + IntToString(nToken) + " oDM: " + GetName(oDM));
//**************************************************************************
string sName = ai_RemoveIllegalCharacters(GetName(oDM));
// Watch to see if the window moves and save.
if(sElem == "window_geometry" && sEvent == "watch")
{
if(GetLocalInt(oDM, AI_NO_NUI_SAVE)) return;
SaveMenuToCampaignDb(oDM, nToken, sWndId);
}
//**************************************************************************
// Widget events.
if(sWndId == "dm" + AI_WIDGET_NUI)
{
//if(GetLocalInt(oDM, AI_NO_NUI_SAVE)) return;
if(sEvent == "click")
{
if(sElem == "btn_open_main")
{
if(IsWindowClosed(oDM, "dm" + AI_COMMAND_NUI)) ai_CreateDMCommandNUI(oDM);
IsWindowClosed(oDM, "dm" + AI_MAIN_NUI);
}
else if(sElem == "btn_camera") ai_SelectCameraView(oDM);
else if(sElem == "btn_inventory") ai_SelectOpenInventory(oDM);
else if(GetStringLeft(sElem, 13) == "btn_cmd_group")
{
ai_DMSelectAction(oDM, sElem);
}
else if(GetStringLeft(sElem, 15) == "btn_exe_plugin_") ai_Plugin_Execute(oDM, sElem, TRUE);
}
else if(sEvent == "mousescroll")
{
float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y"));
if(nMouseScroll == 1.0) // Scroll up
{
if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 1);
}
if(nMouseScroll == -1.0) // Scroll down
{
if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 0);
}
}
else if(sEvent == "mousedown")
{
int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn"));
if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT)
{
if(sElem == "btn_open_main")
{
if(IsWindowClosed(oDM, "dm" + AI_MAIN_NUI)) ai_CreateDMOptionsNUI(oDM);
}
else if(GetStringLeft(sElem, 13) == "btn_cmd_group")
{
ai_SelectToGroup(oDM, sElem);
}
}
}
}
else if(sWndId == "dm" + AI_COMMAND_NUI)
{
if(sEvent == "click")
{
if(sElem == "btn_widget_lock")
{
if(ai_GetDMWidgetButton(oDM, BTN_DM_WIDGET_LOCK))
{
ai_SendMessages(GetName(oDM) + " AI widget unlocked.", AI_COLOR_YELLOW, oDM);
ai_SetDMWidgetButton(oDM, BTN_DM_WIDGET_LOCK, FALSE);
}
else
{
ai_SendMessages(GetName(oDM) + " AI widget locked.", AI_COLOR_YELLOW, oDM);
ai_SetDMWidgetButton(oDM, BTN_DM_WIDGET_LOCK, TRUE);
}
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
}
else if(sElem == "btn_main_menu")
{
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMOptionsNUI(oDM));
}
else if(sElem == "btn_camera") ai_SelectCameraView(oDM);
else if(sElem == "btn_inventory") ai_SelectOpenInventory(oDM);
else if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMSelectAction(oDM, sElem);
else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oDM, sElem, 1);
}
else if(sEvent == "watch")
{
if(sElem == "chbx_cmd_group1_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP1, nToken, sElem);
else if(sElem == "chbx_cmd_group2_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP2, nToken, sElem);
else if(sElem == "chbx_cmd_group3_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP3, nToken, sElem);
else if(sElem == "chbx_cmd_group4_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP4, nToken, sElem);
else if(sElem == "chbx_cmd_group5_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP5, nToken, sElem);
else if(sElem == "chbx_cmd_group6_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP6, nToken, sElem);
else if(sElem == "chbx_camera_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_CAMERA, nToken, sElem);
else if(sElem == "chbx_inventory_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_INVENTORY, nToken, sElem);
if(GetStringLeft(sElem, 12) == "chbx_plugin_" && GetStringRight(sElem, 6) == "_check")
{
int nIndex = StringToInt(GetSubString(sElem, 12, 1));
json jPlugins = ai_GetCampaignDbJson("plugins", sName, AI_DM_TABLE);
json jPlugin = JsonArrayGet(jPlugins, nIndex);
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck));
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
ai_SetCampaignDbJson("plugins", jPlugins, sName, AI_DM_TABLE);
}
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
}
else if(sEvent == "mousescroll")
{
float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y"));
if(nMouseScroll == 1.0) // Scroll up
{
if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 1);
}
if(nMouseScroll == -1.0) // Scroll down
{
if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 0);
}
}
else if(sEvent == "mousedown")
{
int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn"));
if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT)
{
if(GetStringLeft(sElem, 13) == "btn_cmd_group")
{
ai_SelectToGroup(oDM, sElem);
}
}
}
else if(sEvent == "mousescroll")
{
float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y"));
if(nMouseScroll == 1.0) // Scroll up
{
}
else if(nMouseScroll == -1.0) // Scroll down
{
}
}
}
//**************************************************************************
// Main AI events.
if(sWndId == "dm" + AI_MAIN_NUI)
{
if(sEvent == "click")
{
if(sElem == "btn_plugin_manager")
{
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
}
if(sElem == "btn_widget_manager")
{
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMWidgetManagerNUI(oDM));
}
}
if(sEvent == "watch")
{
if(sElem == "txt_max_henchman")
{
int nMaxHenchmen = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
if(nMaxHenchmen < 1) nMaxHenchmen = 1;
if(nMaxHenchmen > 12)
{
nMaxHenchmen = 12;
ai_SendMessages("The maximum henchmen for this mod is 12!", AI_COLOR_RED, oDM);
}
SetMaxHenchmen(nMaxHenchmen);
json jRules = ai_GetCampaignDbJson("rules");
jRules = JsonObjectSet(jRules, AI_RULE_MAX_HENCHMAN, JsonInt(nMaxHenchmen));
ai_SetCampaignDbJson("rules", jRules);
ai_SendMessages("Maximum henchmen has been changed to " + IntToString(nMaxHenchmen), AI_COLOR_YELLOW, oDM);
}
else if(sElem == "txt_ai_difficulty")
{
int nChance = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
if(nChance < 0) nChance = 0;
else if(nChance > 100) nChance = 100;
SetLocalInt(GetModule(), AI_RULE_AI_DIFFICULTY, nChance);
json jRules = ai_GetCampaignDbJson("rules");
jRules = JsonObjectSet(jRules, AI_RULE_AI_DIFFICULTY, JsonInt(nChance));
ai_SetCampaignDbJson("rules", jRules);
}
else if(sElem == "txt_perception_distance")
{
float fDistance = StringToFloat(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
if(fDistance < 10.0) fDistance = 10.0;
else if(fDistance > 60.0) fDistance = 60.0;
SetLocalFloat(GetModule(), AI_RULE_PERCEPTION_DISTANCE, fDistance);
json jRules = ai_GetCampaignDbJson("rules");
jRules = JsonObjectSet(jRules, AI_RULE_PERCEPTION_DISTANCE, JsonFloat(fDistance));
ai_SetCampaignDbJson("rules", jRules);
}
else if(sElem == "txt_inc_hp")
{
int nNumber = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
if(nNumber < 0) nNumber = 0;
else if(nNumber > 100) nNumber = 100;
SetLocalInt(GetModule(), AI_INCREASE_MONSTERS_HP, nNumber);
json jRules = ai_GetCampaignDbJson("rules");
jRules = JsonObjectSet(jRules, AI_INCREASE_MONSTERS_HP, JsonInt(nNumber));
ai_SetCampaignDbJson("rules", jRules);
}
else if(GetStringLeft(sElem, 4) == "chbx")
{
object oModule = GetModule();
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
json jRules = ai_GetCampaignDbJson("rules");
if(sElem == "chbx_moral_check")
{
SetLocalInt(oModule, AI_RULE_MORAL_CHECKS, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_MORAL_CHECKS, JsonInt(bCheck));
}
else if(sElem == "chbx_buff_monsters_check")
{
SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_BUFF_MONSTERS, JsonInt(bCheck));
}
else if(sElem == "chbx_buff_summons_check")
{
SetLocalInt(oModule, AI_RULE_PRESUMMON, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_PRESUMMON, JsonInt(bCheck));
}
else if(sElem == "chbx_ambush_monsters_check")
{
SetLocalInt(oModule, AI_RULE_AMBUSH, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_AMBUSH, JsonInt(bCheck));
}
else if(sElem == "chbx_companions_check")
{
SetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_SUMMON_COMPANIONS, JsonInt(bCheck));
}
else if(sElem == "chbx_advanced_movement_check")
{
SetLocalInt(oModule, AI_RULE_ADVANCED_MOVEMENT, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_ADVANCED_MOVEMENT, JsonInt(bCheck));
}
else if(sElem == "chbx_ilr_check")
{
SetLocalInt(oModule, AI_RULE_ILR, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_ILR, JsonInt(bCheck));
}
else if(sElem == "chbx_umd_check")
{
SetLocalInt(oModule, AI_RULE_ALLOW_UMD, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_ALLOW_UMD, JsonInt(bCheck));
}
else if(sElem == "chbx_use_healingkits_check")
{
SetLocalInt(oModule, AI_RULE_HEALERSKITS, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_HEALERSKITS, JsonInt(bCheck));
}
else if(sElem == "chbx_perm_assoc_check")
{
SetLocalInt(oModule, AI_RULE_PERM_ASSOC, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_PERM_ASSOC, JsonInt(bCheck));
}
else if(sElem == "chbx_corpses_stay_check")
{
SetLocalInt(oModule, AI_RULE_CORPSES_STAY, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_CORPSES_STAY, JsonInt(bCheck));
}
else if(sElem == "chbx_wander_check")
{
SetLocalInt(oModule, AI_RULE_WANDER, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_CORPSES_STAY, JsonInt(bCheck));
}
else if(sElem == "chbx_open_doors_check")
{
SetLocalInt(oModule, AI_RULE_OPEN_DOORS, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_OPEN_DOORS, JsonInt(bCheck));
}
else if(sElem == "chbx_party_scale_check")
{
if(bCheck)
{
SetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP, GetModuleXPScale());
ai_CheckXPPartyScale(oDM);
}
else
{
SetModuleXPScale(GetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE));
}
SetLocalInt(oModule, AI_RULE_PARTY_SCALE, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_PARTY_SCALE, JsonInt(bCheck));
string sText = IntToString(GetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP));
NuiSetBind(oDM, nToken, "chbx_party_scale_tooltip", JsonString(" PEPS adjusts your XP based on party size from (" + sText + ")."));
sText = IntToString(GetModuleXPScale());
NuiSetBind(oDM, nToken, "txt_xp_scale", JsonString(sText));
}
else if(sElem == "chbx_darkness_check")
{
if(bCheck)
{
jRules = ai_AddRestrictedSpell(jRules, SPELL_DARKNESS);
jRules = ai_AddRestrictedSpell(jRules, 159);
jRules = ai_AddRestrictedSpell(jRules, SPELLABILITY_AS_DARKNESS);
jRules = ai_AddRestrictedSpell(jRules, 688); // WildShape_Darkness
}
else
{
jRules = ai_AddRestrictedSpell(jRules, SPELL_DARKNESS, FALSE);
jRules = ai_AddRestrictedSpell(jRules, 159, FALSE);
jRules = ai_AddRestrictedSpell(jRules, SPELLABILITY_AS_DARKNESS, FALSE);
jRules = ai_AddRestrictedSpell(jRules, 688, FALSE); // WildShape_Darkness
}
}
else if(sElem == "chbx_dispels_check")
{
if(bCheck)
{
jRules = ai_AddRestrictedSpell(jRules, SPELL_LESSER_DISPEL);
jRules = ai_AddRestrictedSpell(jRules, SPELL_DISPEL_MAGIC);
jRules = ai_AddRestrictedSpell(jRules, SPELL_GREATER_DISPELLING);
jRules = ai_AddRestrictedSpell(jRules, SPELL_MORDENKAINENS_DISJUNCTION);
}
else
{
jRules = ai_AddRestrictedSpell(jRules, SPELL_LESSER_DISPEL, FALSE);
jRules = ai_AddRestrictedSpell(jRules, SPELL_DISPEL_MAGIC, FALSE);
jRules = ai_AddRestrictedSpell(jRules, SPELL_GREATER_DISPELLING, FALSE);
jRules = ai_AddRestrictedSpell(jRules, SPELL_MORDENKAINENS_DISJUNCTION, FALSE);
}
}
else if(sElem == "chbx_timestop_check")
{
if(bCheck) jRules = ai_AddRestrictedSpell(jRules, SPELL_TIME_STOP);
else jRules = ai_AddRestrictedSpell(jRules, SPELL_TIME_STOP, FALSE);
}
ai_SetCampaignDbJson("rules", jRules);
}
}
else if(sEvent == "mousescroll")
{
float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y"));
if(nMouseScroll == 1.0) // Scroll up
{
// Follow range is only changed on non-pc's
if(sElem == "lbl_perc_dist") ai_RulePercDistInc(oDM, GetModule(), 1, nToken);
}
else if(nMouseScroll == -1.0) // Scroll down
{
// Follow range is only changed on non-pc's
if(sElem == "lbl_perc_dist") ai_RulePercDistInc(oDM, GetModule(), -1, nToken);
}
}
}
//**************************************************************************
// Plugins events.
if(sWndId == "dmai_plugin_nui")
{
string sName = ai_RemoveIllegalCharacters(GetName(oDM));
json jPlugins = ai_GetCampaignDbJson("plugins");
if(sEvent == "click")
{
if(sElem == "btn_load_plugins")
{
string sScript = JsonGetString(NuiGetBind (oDM, nToken, "txt_plugin"));
if(JsonGetType(JsonArrayGet(jPlugins, 0)) == JSON_TYPE_NULL) jPlugins = JsonArray();
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_buffing");
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_forcerest");
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_henchmen");
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_crafting");
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_mod_set");
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_debug");
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_test");
ai_SetCampaignDbJson("plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
}
if(sElem == "btn_check_plugins")
{
int nIndex;
json jPlugin = JsonArrayGet(jPlugins, nIndex);
while(JsonGetType(jPlugin) != JSON_TYPE_NULL)
{
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(TRUE));
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
jPlugin = JsonArrayGet(jPlugins, ++nIndex);
}
ai_SetCampaignDbJson("plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
}
if(sElem == "btn_clear_plugins")
{
int nIndex;
json jPlugin = JsonArrayGet(jPlugins, nIndex);
while(JsonGetType(jPlugin) != JSON_TYPE_NULL)
{
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(FALSE));
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
jPlugin = JsonArrayGet(jPlugins, ++nIndex);
}
ai_SetCampaignDbJson("plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
}
else if(sElem == "btn_add_plugin")
{
string sScript = JsonGetString(NuiGetBind (oDM, nToken, "txt_plugin"));
if(JsonGetType(JsonArrayGet(jPlugins, 0)) == JSON_TYPE_NULL) jPlugins = JsonArray();
jPlugins = ai_Plugin_Add(oDM, jPlugins, sScript);
ai_SetCampaignDbJson("plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
}
else if(GetStringLeft(sElem, 18) == "btn_remove_plugin_")
{
int nIndex = StringToInt(GetStringRight(sElem, 1));
jPlugins = JsonArrayDel(jPlugins, nIndex);
ai_SetCampaignDbJson("plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
}
else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oDM, sElem, 2);
}
else if(sEvent == "watch")
{
if(GetStringLeft(sElem, 12) == "chbx_plugin_" && GetStringRight(sElem, 6) == "_check")
{
int nIndex = StringToInt(GetSubString(sElem, 12, 1));
json jPlugin = JsonArrayGet(jPlugins, nIndex);
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck));
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
ai_SetCampaignDbJson("plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
}
}
}
if(sWndId == "dm_widget_manager_nui")
{
//SendMessageToDM(oDM, "sEvent: " + sEvent + " sElem: " + sElem);
if(sEvent == "click")
{
if(sElem == "btn_clear_buttons")
{
object oModule = GetModule();
SetLocalInt(oModule, sDMWidgetAccessVarname, 0);
SetLocalInt(oModule, sDMAIAccessVarname, 0);
json jRules = ai_GetCampaignDbJson("rules");
jRules = JsonObjectSet(jRules, sDMWidgetAccessVarname, JsonInt(0));
jRules = JsonObjectSet(jRules, sDMAIAccessVarname, JsonInt(0));
ai_SetCampaignDbJson("rules", jRules);
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMWidgetManagerNUI(oDM));
return;
}
else if(sElem == "btn_check_buttons")
{
object oModule = GetModule();
SetLocalInt(oModule, sDMWidgetAccessVarname, 7340028);
SetLocalInt(oModule, sDMAIAccessVarname, 203423743);
json jRules = ai_GetCampaignDbJson("rules");
jRules = JsonObjectSet(jRules, sDMWidgetAccessVarname, JsonInt(7340028));
jRules = JsonObjectSet(jRules, sDMAIAccessVarname, JsonInt(203423743));
ai_SetCampaignDbJson("rules", jRules);
DelayCommand(0.0, NuiDestroy(oDM, nToken));
DelayCommand(0.1, ai_CreateDMWidgetManagerNUI(oDM));
return;
}
SetLocalInt(oDM, "CHBX_SKIP", TRUE);
DelayCommand(2.0, DeleteLocalInt(oDM, "CHBX_SKIP"));
if(sElem == "btn_cmd_action") NuiSetBind(oDM, nToken, "chbx_cmd_action_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_ACTION)));
else if(sElem == "btn_cmd_guard") NuiSetBind(oDM, nToken, "chbx_cmd_guard_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_GUARD)));
else if(sElem == "btn_cmd_hold") NuiSetBind(oDM, nToken, "chbx_cmd_hold_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_HOLD)));
else if(sElem == "btn_cmd_attack") NuiSetBind(oDM, nToken, "chbx_cmd_attack_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_ATTACK)));
else if(sElem == "btn_cmd_follow") NuiSetBind(oDM, nToken, "chbx_cmd_follow_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_FOLLOW)));
else if(sElem == "btn_follow_target") NuiSetBind(oDM, nToken, "chbx_follow_target_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_FOLLOW_TARGET)));
else if(sElem == "btn_cmd_search") NuiSetBind(oDM, nToken, "chbx_cmd_search_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_SEARCH)));
else if(sElem == "btn_cmd_stealth") NuiSetBind(oDM, nToken, "chbx_cmd_stealth_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_STEALTH)));
else if(sElem == "btn_cmd_ai_script") NuiSetBind(oDM, nToken, "chbx_cmd_ai_script_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_AI_SCRIPT)));
else if(sElem == "btn_cmd_place_trap") NuiSetBind(oDM, nToken, "chbx_cmd_place_trap_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_PLACE_TRAP)));
else if(sElem == "btn_quick_widget") NuiSetBind(oDM, nToken, "chbx_quick_widget_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_SPELL_WIDGET)));
else if(sElem == "btn_spell_memorize") NuiSetBind(oDM, nToken, "chbx_spell_memorize_check", JsonBool(!ai_GetDMWAccessButton(BTN_DM_CMD_MEMORIZE)));
else if(sElem == "btn_buff_short") NuiSetBind(oDM, nToken, "chbx_buff_short_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_SHORT)));
else if(sElem == "btn_buff_long") NuiSetBind(oDM, nToken, "chbx_buff_long_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_LONG)));
else if(sElem == "btn_buff_all") NuiSetBind(oDM, nToken, "chbx_buff_all_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_ALL)));
else if(sElem == "btn_buff_rest") NuiSetBind(oDM, nToken, "chbx_buff_rest_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_REST)));
else if(sElem == "btn_jump_to") NuiSetBind(oDM, nToken, "chbx_jump_to_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_JUMP_TO)));
else if(sElem == "btn_ghost_mode") NuiSetBind(oDM, nToken, "chbx_ghost_mode_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_GHOST_MODE)));
else if(sElem == "btn_camera") NuiSetBind(oDM, nToken, "chbx_camera_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_CAMERA)));
else if(sElem == "btn_inventory") NuiSetBind(oDM, nToken, "chbx_inventory_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_INVENTORY)));
else if(sElem == "btn_familiar") NuiSetBind(oDM, nToken, "chbx_familiar_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_FAMILIAR)));
else if(sElem == "btn_companion") NuiSetBind(oDM, nToken, "chbx_companion_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_COMPANION)));
else if(sElem == "btn_ai") NuiSetBind(oDM, nToken, "chbx_ai_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_FOR_PC)));
else if(sElem == "btn_quiet") NuiSetBind(oDM, nToken, "chbx_quiet_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_REDUCE_SPEECH)));
else if(sElem == "btn_ranged") NuiSetBind(oDM, nToken, "chbx_ranged_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_USE_RANGED)));
else if(sElem == "btn_search") NuiSetBind(oDM, nToken, "chbx_search_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_USE_SEARCH)));
else if(sElem == "btn_stealth") NuiSetBind(oDM, nToken, "chbx_stealth_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_USE_STEALTH)));
else if(sElem == "btn_open_door") NuiSetBind(oDM, nToken, "chbx_open_door_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_OPEN_DOORS)));
else if(sElem == "btn_traps") NuiSetBind(oDM, nToken, "chbx_traps_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_REMOVE_TRAPS)));
else if(sElem == "btn_pick_locks") NuiSetBind(oDM, nToken, "chbx_pick_locks_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_PICK_LOCKS)));
else if(sElem == "btn_bash_locks") NuiSetBind(oDM, nToken, "chbx_bash_locks_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_BASH_LOCKS)));
else if(sElem == "btn_magic_level") NuiSetBind(oDM, nToken, "chbx_magic_level_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_MAGIC_LEVEL)));
else if(sElem == "btn_spontaneous") NuiSetBind(oDM, nToken, "chbx_spontaneous_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_NO_SPONTANEOUS)));
else if(sElem == "btn_magic") NuiSetBind(oDM, nToken, "chbx_magic_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_USE)));
else if(sElem == "btn_magic_items") NuiSetBind(oDM, nToken, "chbx_magic_items_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_ITEM_USE)));
else if(sElem == "btn_def_magic") NuiSetBind(oDM, nToken, "chbx_def_magic_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_DEF_MAGIC_USE)));
else if(sElem == "btn_off_magic") NuiSetBind(oDM, nToken, "chbx_off_magic_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_OFF_MAGIC_USE)));
else if(sElem == "btn_heal_out") NuiSetBind(oDM, nToken, "chbx_heal_out_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_HEAL_OUT)));
else if(sElem == "btn_heal_in") NuiSetBind(oDM, nToken, "chbx_heal_in_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_HEAL_IN)));
else if(sElem == "btn_heals_onoff") NuiSetBind(oDM, nToken, "chbx_heals_onoff_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_STOP_SELF_HEALING)));
else if(sElem == "btn_healp_onoff") NuiSetBind(oDM, nToken, "chbx_healp_onoff_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_STOP_PARTY_HEALING)));
else if(sElem == "btn_loot") NuiSetBind(oDM, nToken, "chbx_loot_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_LOOT)));
else if(sElem == "btn_ignore_assoc") NuiSetBind(oDM, nToken, "chbx_ignore_assoc_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_IGNORE_ASSOCIATES)));
else if(sElem == "btn_ignore_traps") NuiSetBind(oDM, nToken, "chbx_ignore_traps_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_IGNORE_TRAPS)));
else if(sElem == "btn_perc_range") NuiSetBind(oDM, nToken, "chbx_perc_range_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_PERC_RANGE)));
}
if(sEvent == "watch")
{
if(GetLocalInt(oDM, "CHBX_SKIP")) return;
if(sElem == "chbx_cmd_action_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_ACTION, nToken, sElem);
else if(sElem == "chbx_cmd_guard_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_GUARD, nToken, sElem);
else if(sElem == "chbx_cmd_hold_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_HOLD, nToken, sElem);
else if(sElem == "chbx_cmd_attack_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_ATTACK, nToken, sElem);
else if(sElem == "chbx_cmd_follow_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_FOLLOW, nToken, sElem);
else if(sElem == "chbx_follow_target_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_FOLLOW_TARGET, nToken, sElem);
else if(sElem == "chbx_cmd_search_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_SEARCH, nToken, sElem);
else if(sElem == "chbx_cmd_stealth_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_STEALTH, nToken, sElem);
else if(sElem == "chbx_cmd_ai_script_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_AI_SCRIPT, nToken, sElem);
else if(sElem == "chbx_cmd_place_trap_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_PLACE_TRAP, nToken, sElem);
else if(sElem == "chbx_quick_widget_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_SPELL_WIDGET, nToken, sElem);
else if(sElem == "chbx_spell_memorize_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_DM_CMD_MEMORIZE, nToken, sElem);
else if(sElem == "chbx_buff_short_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_SHORT, nToken, sElem);
else if(sElem == "chbx_buff_long_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_LONG, nToken, sElem);
else if(sElem == "chbx_buff_all_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_ALL, nToken, sElem);
else if(sElem == "chbx_buff_rest_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_REST, nToken, sElem);
else if(sElem == "chbx_jump_to_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_JUMP_TO, nToken, sElem);
else if(sElem == "chbx_ghost_mode_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_GHOST_MODE, nToken, sElem);
else if(sElem == "chbx_camera_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_CAMERA, nToken, sElem);
else if(sElem == "chbx_inventory_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_INVENTORY, nToken, sElem);
else if(sElem == "chbx_familiar_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_FAMILIAR, nToken, sElem);
else if(sElem == "chbx_companion_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_COMPANION, nToken, sElem);
else if(sElem == "chbx_ai_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_FOR_PC, nToken, sElem);
else if(sElem == "chbx_quiet_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_REDUCE_SPEECH, nToken, sElem);
else if(sElem == "chbx_ranged_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_USE_RANGED, nToken, sElem);
else if(sElem == "chbx_search_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_USE_SEARCH, nToken, sElem);
else if(sElem == "chbx_stealth_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_USE_STEALTH, nToken, sElem);
else if(sElem == "chbx_open_door_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_OPEN_DOORS, nToken, sElem);
else if(sElem == "chbx_traps_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_REMOVE_TRAPS, nToken, sElem);
else if(sElem == "chbx_pick_locks_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_PICK_LOCKS, nToken, sElem);
else if(sElem == "chbx_bash_locks_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_BASH_LOCKS, nToken, sElem);
else if(sElem == "chbx_magic_level_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_MAGIC_LEVEL, nToken, sElem);
else if(sElem == "chbx_spontaneous_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_NO_SPONTANEOUS, nToken, sElem);
else if(sElem == "chbx_magic_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_NO_MAGIC_USE, nToken, sElem);
else if(sElem == "chbx_magic_items_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_NO_MAGIC_ITEM_USE, nToken, sElem);
else if(sElem == "chbx_def_magic_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_DEF_MAGIC_USE, nToken, sElem);
else if(sElem == "chbx_off_magic_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_OFF_MAGIC_USE, nToken, sElem);
else if(sElem == "chbx_heal_out_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_HEAL_OUT, nToken, sElem);
else if(sElem == "chbx_heal_in_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_HEAL_IN, nToken, sElem);
else if(sElem == "chbx_heals_onoff_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_STOP_SELF_HEALING, nToken, sElem);
else if(sElem == "chbx_healp_onoff_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_STOP_PARTY_HEALING, nToken, sElem);
else if(sElem == "chbx_loot_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_LOOT, nToken, sElem);
else if(sElem == "chbx_ignore_assoc_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_IGNORE_ASSOCIATES, nToken, sElem);
else if(sElem == "chbx_ignore_traps_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_IGNORE_TRAPS, nToken, sElem);
else if(sElem == "chbx_perc_range_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_PERC_RANGE, nToken, sElem);
}
}
}
void ai_SetDMWidgetButtonToCheckbox(object oDM, int nButton, int nToken, string sElem)
{
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
ai_SetDMWidgetButton(oDM, nButton, bCheck);
}
void ai_SetDMWAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem)
{
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
ai_SetDMWAccessButton(nButton, bCheck);
}
void ai_SetDMAIAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem)
{
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
ai_SetDMAIAccessButton(nButton, bCheck);
}
void ai_RulePercDistInc(object oDM, object oModule, int nIncrement, int nToken)
{
int nAdjustment = GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE) + nIncrement;
if(nAdjustment < 8 || nAdjustment > 11) return;
SetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE, nAdjustment);
string sText;
if(nAdjustment == 8) sText = " Monster perception: Short [10 Sight / 10 Listen]";
else if(nAdjustment == 9) sText = " Monster perception: Medium [20 Sight / 20 Listen]";
else if(nAdjustment == 10) sText = " Monster perception: Long [35 Sight / 20 Listen]";
else sText = " Monster perception: Default [Monster's default values]";
NuiSetBind(oDM, nToken, "lbl_perc_dist_label", JsonString(sText));
json jRules = ai_GetCampaignDbJson("rules");
jRules = JsonObjectSet(jRules, AI_RULE_MON_PERC_DISTANCE, JsonInt(nAdjustment));
ai_SetCampaignDbJson("rules", jRules);
}
json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE)
{
object oModule = GetModule();
json jRSpells = GetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS);
int nIndex, nMaxIndex = JsonGetLength(jRSpells);
if(bRestrict)
{
while(nIndex < nMaxIndex)
{
if(JsonGetInt(JsonArrayGet(jRSpells, nIndex)) == nSpell) return jRules;
nIndex++;
}
jRSpells = JsonArrayInsert(jRSpells, JsonInt(nSpell));
}
else
{
while(nIndex < nMaxIndex)
{
if(JsonGetInt(JsonArrayGet(jRSpells, nIndex)) == nSpell)
{
jRSpells = JsonArrayDel(jRSpells, nIndex);
break;
}
nIndex++;
}
}
SetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS, jRSpells);
return JsonObjectSet(jRules, AI_RULE_RESTRICTED_SPELLS, jRSpells);
}
void ai_SelectToGroup(object oDM, string sElem)
{
string sGroup = GetStringRight(sElem, 1);
SetLocalString(oDM, AI_TARGET_MODE, "DM_SELECT_GROUP" + sGroup);
ai_SendMessages("Select a creature to add to group " + sGroup + ". Selecting yourself will clear group1.", AI_COLOR_YELLOW, oDM);
EnterTargetingMode(oDM, OBJECT_TYPE_CREATURE, MOUSECURSOR_PICKUP, MOUSECURSOR_PICKUP_DOWN);
}
void ai_DMSelectAction(object oDM, string sElem)
{
string sGroup = GetStringRight(sElem, 1);
SetLocalString(oDM, AI_TARGET_MODE, "DM_ACTION_GROUP" + sGroup);
ai_SendMessages(GetName(oDM) + " select an action for group" + sGroup + ".", AI_COLOR_YELLOW, oDM);
EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
}
void ai_DMChangeMoveSpeed(object oDM, string sElem, int nSpeed)
{
string sGroup = GetStringRight(sElem, 1);
json jGroup = GetLocalJson(oDM, "DM_GROUP" + sGroup);
if(JsonGetType(jGroup) == JSON_TYPE_NULL)
{
ai_SendMessages("This group does not contain any creatures!", AI_COLOR_RED, oDM);
return;
}
jGroup = JsonArraySet(jGroup, 0, JsonInt(nSpeed));
SetLocalJson(oDM, "DM_GROUP" + sGroup, jGroup);
object oLeader = GetObjectByUUID(JsonGetString(JsonArrayGet(jGroup, 1)));
string sName = GetName(oLeader);
string sText = " " + sName + "'s group";
if(nSpeed == 0) sText += " [Walk]";
else sText += " [Run]";
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText));
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText));
}

View File

@ -0,0 +1,23 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_onclientload
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Monster OnClientLoad script;
This will fire when the client is loading.
If you have your own OnClientLoad event script just take the below
script lines and add them into your OnClientLoad script.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_menus_dm"
#include "0i_module"
void main()
{
object oCreature = OBJECT_SELF;
// This can be moved to the OnClientLoad script event of your module.
if(ai_GetIsCharacter(oCreature)) ai_CheckPCStart(oCreature);
// If this is a server you can add this as well.
else if(AI_SERVER && (GetIsDM(oCreature) || GetIsPlayerDM(oCreature)))
{
ai_CheckPCStart(oCreature);
}
}

View File

@ -0,0 +1,154 @@
/*//////////////////////////////////////////////////////////////////////////////
Script Name: 0e_player_target
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
OnPlayerTarget event script
Used to allow player targeting while passing any module player targeting
script through to work as intended.
We Use a string variable upon the player using the targeting mode to define the
action of the target.
AI_TARGET_MODE is the constant used.
AI_TARGET_ASSOCIATE is the associate that triggered the target mode.
/*//////////////////////////////////////////////////////////////////////////////
#include "0i_player_target"
void main()
{
object oPC = GetLastPlayerToSelectTarget();
// Get any plugin target scripts and run it instead of this one.
string sPluginTargetScript = GetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT);
if(sPluginTargetScript != "")
{
DeleteLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT);
ExecuteScript(sPluginTargetScript, oPC);
// Remove the plugin script as it must be set each time the plugin uses the target event.
}
else
{
// Get the targeting mode data
object oTarget = GetTargetingModeSelectedObject();
vector vTarget = GetTargetingModeSelectedPosition();
location lLocation = Location(GetArea(oPC), vTarget, GetFacing(oPC));
object oAssociate = GetLocalObject(oPC, AI_TARGET_ASSOCIATE);
string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE);
// ********************* Exiting Target Actions ************************
// If the user manually exited targeting mode without selecting a target, return
if(!GetIsObjectValid(oTarget) && vTarget == Vector())
{
if(sTargetMode == "ASSOCIATE_ACTION_ALL")
{
ai_SendMessages("You have exited selecting an action for the party.", AI_COLOR_YELLOW, oPC);
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
{
if(GetLocalInt(oPC, sGhostModeVarname)) ai_OriginalRemoveAllActionMode(oPC);
}
else ai_RemoveAllActionMode(oPC);
}
else if(sTargetMode == "ASSOCIATE_ACTION")
{
ai_SendMessages("You have exited selecting an action for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC);
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
{
if(GetLocalInt(oPC, sGhostModeVarname))
{
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
DeleteLocalInt(oAssociate, sGhostModeVarname);
}
}
else
{
ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, FALSE);
if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) && !ai_GetAIMode(oPC, AI_MODE_GHOST) &&
GetLocalInt(oAssociate, sGhostModeVarname))
{
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
DeleteLocalInt(oAssociate, sGhostModeVarname);
}
ExecuteScript("nw_ch_ac1", oAssociate);
}
}
else if(sTargetMode == "ASSOCIATE_GET_TRAP")
{
ai_SendMessages(GetName(oAssociate) + " has exited selecing a trap!", AI_COLOR_YELLOW, oPC);
}
else if(sTargetMode == "ASSOCIATE_PLACE_TRAP")
{
ai_SendMessages(GetName(oAssociate) + " has exited placing the trap!", AI_COLOR_YELLOW, oPC);
}
else if(sTargetMode == "DM_SELECT_CAMERA_VIEW")
{
AttachCamera(oPC, oPC);
ai_SendMessages(GetName(oPC) + " has defaulted camera view back to the player!", AI_COLOR_YELLOW, oPC);
}
return;
}
// ************************* Targeted Actions **************************
else
{
// This action makes an associates move to vTarget.
if(sTargetMode == "ASSOCIATE_ACTION_ALL")
{
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
{
ai_OriginalActionAllAssociates(oPC, oTarget, lLocation);
}
else ai_ActionAllAssociates(oPC, oTarget, lLocation);
}
else if(sTargetMode == "ASSOCIATE_ACTION")
{
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
{
AssignCommand(oAssociate, ai_OriginalActionAssociate(oPC, oTarget, lLocation));
}
else AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation));
}
else if(sTargetMode == "ASSOCIATE_FOLLOW_TARGET") ai_SelectFollowTarget(oPC, oAssociate, oTarget);
else if(sTargetMode == "ASSOCIATE_GET_TRAP") ai_SelectTrap(oPC, oAssociate, oTarget);
else if(sTargetMode == "ASSOCIATE_PLACE_TRAP") AssignCommand(oAssociate, ai_PlaceTrap(oPC, lLocation));
else if(sTargetMode == "ASSOCIATE_USE_ITEM")
{
if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID;
ai_UseWidgetItem(oPC, oAssociate, oTarget, lLocation);
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
}
else if(sTargetMode == "ASSOCIATE_USE_FEAT")
{
if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID;
ai_UseWidgetFeat(oPC, oAssociate, oTarget, lLocation);
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
}
else if(sTargetMode == "ASSOCIATE_CAST_SPELL")
{
if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID;
ai_CastWidgetSpell(oPC, oAssociate, oTarget, lLocation);
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
}
else if(sTargetMode == "DM_SELECT_CAMERA_VIEW")
{
AttachCamera(oPC, oTarget);
ai_SendMessages(GetName(oPC) + " has changed the camera view to " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC);
}
else if(sTargetMode == "DM_SELECT_OPEN_INVENTORY")
{
if(LineOfSightObject(oPC, oTarget))
{
OpenInventory(oTarget, oPC);
ai_SendMessages("You have opened the inventory of "+ GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC);
}
else ai_SendMessages(GetName(oTarget) + " is not in your line of sight!", AI_COLOR_YELLOW, oPC);
}
else if(GetStringLeft(sTargetMode, 15) == "DM_SELECT_GROUP")
{
ai_AddToGroup(oPC, oTarget, sTargetMode);
}
else if(GetStringLeft(sTargetMode, 15) == "DM_ACTION_GROUP")
{
ai_DMAction(oPC, oTarget, lLocation, sTargetMode);
}
// Get saved module player target script and execute it for pass through compatibility.
string sModuleTargetScript = GetLocalString(GetModule(), AI_MODULE_TARGET_EVENT);
ExecuteScript(sModuleTargetScript);
}
}
}

View File

@ -0,0 +1,78 @@
/*//////////////////////////////////////////////////////////////////////////////
// Script Name: 0e_prc_ch_events
////////////////////////////////////////////////////////////////////////////////
associate event handler while using the PRC.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
#include "x0_i0_assoc"
void main()
{
object oCreature = OBJECT_SELF;
int nEvent = GetCurrentlyRunningEvent();
//WriteTimestampedLogEntry("0e_prc_ch_events [13] " + GetName(oCreature) + " nEvent: " + IntToString(nEvent));
switch (nEvent)
{
case EVENT_SCRIPT_CREATURE_ON_HEARTBEAT:
{
if(GetLocalInt(oCreature, "CohortID")) ExecuteScript("prc_ai_coh_hb");
ExecuteScript("nw_ch_ac1", oCreature);
ExecuteScript("prc_npc_hb", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_NOTICE:
{
ExecuteScript("nw_ch_ac2", oCreature);
ExecuteScript("prc_npc_percep", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_DIALOGUE:
{
//if(GetLocalInt(oCreature, "CohortID")) ExecuteScript("prc_ai_coh_conv");
ExecuteScript("nw_ch_ac4", oCreature);
//ExecuteScript("prc_npc_conv", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED:
{
ExecuteScript("nw_ch_ac5", oCreature);
ExecuteScript("prc_npc_physatt", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_DAMAGED:
{
ExecuteScript("nw_ch_ac6", oCreature);
ExecuteScript("prc_npc_damaged", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT:
{
ExecuteScript("nw_ch_acb", oCreature);
ExecuteScript("prc_npc_spellat", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND:
{
ExecuteScript("nw_ch_ac3", oCreature);
ExecuteScript("prc_npc_combat", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR:
{
ExecuteScript("nw_ch_ace", oCreature);
ExecuteScript("prc_npc_blocked", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_RESTED:
{
ExecuteScript("nw_ch_aca", oCreature);
//ExecuteScript("prc_npc_rested", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_DISTURBED:
{
ExecuteScript("nw_ch_ac8", oCreature);
ExecuteScript("prc_npc_disturb", oCreature);
break;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: 0i_color
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
Include scripts that are used to change the color of names and text.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Basic color codes. Message Notes
const string AI_COLOR_BLACK = "000"; // <c > <c\x20\x20\x20> Nothing.
const string AI_COLOR_WHITE = "999"; // <cÿÿÿ> <c\xFF\xFF\xFF> _Debug messages.
const string AI_COLOR_GRAY = "666"; // <cªªª> <c\xAA\xAA\xAA> Server messages
const string AI_COLOR_YELLOW = "990"; // <cÿÿ > <c\xFF\xFF\x20> Generic messages to players.
const string AI_COLOR_DARK_YELLOW = "660"; // <c ª> <c\xAA\xAA\x20>
const string AI_COLOR_RED = "900"; // <cÿ > <c\xFF\x20\x20> Negative message to players.
const string AI_COLOR_DARK_RED = "600"; // <c ª> <c\xAA\x20\x20>
const string AI_COLOR_GREEN = "080"; // <c ÿ > <c\x20\xFF\x20> Positive message to players.
const string AI_COLOR_DARK_GREEN = "060"; // <c ª > <c\x20\xAA\x20>
const string AI_COLOR_BLUE = "009"; // <c ÿ> <c\x20\x20\xFF>
const string AI_COLOR_DARK_BLUE = "006"; // <c ª> <c\x20\x20\xAA> In game descriptive text.
const string AI_COLOR_CYAN = "099"; // <c ÿÿ> <c\x20\xFF\xFF>
const string AI_COLOR_DARK_CYAN = "066"; // <c ªª> <c\x20\xAA\xAA>
const string AI_COLOR_MAGENTA = "909"; // <cÿ ÿ> <c\xFF\x20\xFF>
const string AI_COLOR_DARK_MAGENTA = "606";// <cª ª> <c\xAA\x20\xAA>
const string AI_COLOR_LIGHT_MAGENTA = "868"; // <âcâ> <c\xAA\xE2\xAA> Combat text: Enemy name color.
const string AI_COLOR_ORANGE = "950"; // <cÿª > <c\xFF\x8E\x20>
const string AI_COLOR_DARK_ORANGE = "940"; // <cÿq > <c\xFF\x71\x20> Combat text: base text color.
const string AI_COLOR_GOLD = "860"; // <c⪠> <c\xE2\xAA\x20>
// Strips the color codes from sText
string ai_StripColorCodes(string sText);
// This function will make sString be the specified color
// as specified in sRGB. RGB is the Red, Green, and Blue
// Each color can have a value from 0 to 9.
// 1 - 0(20)[ ] 142 - 5(8E)[?]
// 32 - 1(20)[ ] 170 - 6(AA)[ª]
// 57 - 2(39)[9] 198 - 7(C6)[Æ]
// 85 - 3(55)[U] 226 - 8(E2)[â]
// 113 - 4(71)[q] 255 - 9(FE)[ÿ]
string ai_AddColorToText(string sText, string sRGB = AI_COLOR_WHITE);
string ai_StripColorCodes(string sText)
{
string sColorCode, sChar;
int nStringLength = GetStringLength(sText);
int i = FindSubString(sText, "<c", 0);
while(i != -1)
{
sText = GetStringLeft(sText, i) + GetStringRight(sText, nStringLength -(i + 6));
nStringLength = GetStringLength(sText);
i = FindSubString(sText, "<c", i);
}
i = FindSubString(sText, "</", 0);
while(i != -1)
{
sText = GetStringLeft(sText, i) + GetStringRight(sText, nStringLength -(i + 4));
nStringLength = GetStringLength(sText);
i = FindSubString(sText, "</", i);
}
return sText;
}
string ai_AddColorToText(string sText, string sRGB = AI_COLOR_WHITE)
{
// Old info The magic characters(padded -- the last three characters are the same).
string sColorCodes = "\x20\x20\x39\x55\x71\x8E\xAA\xC6\xE2\xFF";
if(FindSubString(sText, "<c", 0) != -1) sText = ai_StripColorCodes(sText);
return "<c" + // Begin the color token.
GetSubString(sColorCodes, StringToInt(GetSubString(sRGB, 0, 1)), 1) + // red
GetSubString(sColorCodes, StringToInt(GetSubString(sRGB, 1, 1)), 1) + // green
GetSubString(sColorCodes, StringToInt(GetSubString(sRGB, 2, 1)), 1) + // blue
">" + // End the color token
sText + "</c>";
}

3498
src/module/nss/0i_combat.nss Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,667 @@
/*//////////////////////////////////////////////////////////////////////////////
// Name: 0i_constants
// Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Include script for handling all constants for the ai.
These constants are static and can only be changed in the toolset.
Changes to any constants will not take effect until the scripts are recompiled.
*///////////////////////////////////////////////////////////////////////////////
const string PHILOS_VERSION = "Philos' Enhancing Player System (PEPS) version:07.12.25";
// The following constants are designed to be changed to allow the AI to work
// differently based on what a developer wants.
// If you change these constants make sure the database has been removed
// so the ai_SetAIRules() will rewrite the new server rule values.
// File Name: peps_database.sqlite3
//********************************** SERVER ***********************************
// Turn On/Off Debug. You can only use the debug with the pi_debug/pe_debug scripts.
// This will only work if you are using the PEPS menu system.
const int AI_DEBUG = FALSE;
// Defines if we are compiling for single player or a server. Always on for servers!
const int AI_SERVER = FALSE;
// The number of classes allowed for a creature to take in the server/module.
const int AI_MAX_CLASSES_PER_CHARACTER = 8;
// Taunts cool down time before the AI attemps another Taunt.
const int AI_TAUNT_COOLDOWN = 3;
// Animal Empathy cool down time before the AI attemps another check.
const int AI_EMPATHY_COOLDOWN = 3;
// Arcane Spell failure% or less than, for a caster to still try to cast a spell.
const int AI_ASF_WILL_USE = 15;
// Monsters chance to heal while in combat per round.
const int AI_MONSTER_HEAL_IN_COMBAT_CHANCE = 70;
// Monsters chance to heal when out of combat per heart beat.
const int AI_MONSTER_HEAL_OUT_COMBAT_CHANCE = 70;
// Allows Henchman to have a widget if using the henchman AI.
const int AI_HENCHMAN_WIDGET = TRUE;
// Change the Custom token number if it conflicts with your server.
const int AI_BASE_CUSTOM_TOKEN = 1000;
// Delay between creatures casting Buff spells. Must be minimum of 0.1 seconds.
const float AI_HENCHMAN_BUFF_DELAY = 0.2;
//******************* These can be changed within the game *******************
// Moral checks on or off. If wounded they will make Will saves, if they fail the flee.
const int AI_MORAL_CHECKS = FALSE;
// Allows monsters to prebuff before combat starts.
const int AI_PREBUFF = TRUE;
// Allows monsters cast summons spells when prebuffing.
const int AI_PRESUMMONS = TRUE;
// Allows monsters to use tactical AI scripts such as ambush, flanker, ranged.
const int AI_TACTICAL = TRUE;
// Enemies may summon familiars and Animal companions and will be randomized.
const int AI_SUMMON_COMPANIONS = FALSE;
// Allow the AI to move during combat base on the situation and action taking.
const int AI_ADVANCED_MOVEMENT = TRUE;
// Follow Item Level Restrictions for AI.
const int AI_ITEM_LEVEL_RESTRICTIONS = FALSE;
// Allow the AI to use Use Magic Device.
const int AI_USE_MAGIC_DEVICE = TRUE;
// Allow the AI to use healing kits.
const int AI_HEALING_KITS = TRUE;
// Associates are permanent and don't get removed when the master dies.
const int AI_COMPANIONS_PERMANENT = FALSE;
// Monster AI's chance (0 to 100) to attack the weakest target instead of the nearest.
// The higher the number the harder the encounter with monsters!
const int AI_TARGET_WEAKEST = 0;
// Variable that can change the distance creatures will come and attack after
// hearing a shout from an ally that sees or hears an enemy.
// Or when searching for an invisible, heard enemy.
// 10.0 Short, 30.0 Average, 40.0 Long, 60.0 Huge.
const float AI_SEARCH_DISTANCE = 30.0;
// Enemy corpses remain on the floor instead of dissappearing.
const int AI_CORPSE_REMAIN = FALSE;
// Monsters will wander around when not in combat.
const int AI_WANDER = FALSE;
// Variable distance monsters can wander away from their spawn point.
const float AI_WANDER_DISTANCE = 0.0;
// Variable that allows monsters to open doors when wandering around out of combat.
const int AI_OPEN_DOORS = FALSE;
// Monster's actual perception distance.
// 8 Short(10 sight/listen) 9 Medium(20 sight/listen) 10 Long(35 sight/20 listen)
// 11 Default(Based on appearance.2da Most creatures use 9, bosses use 10).
const int AI_MONSTER_PERCEPTION = 11;
// Should the AI auto adjust the XP scale to remove party size penalty?
const int AI_PARTY_SCALE = FALSE;
//**************************** DM Based Constants ****************************
// The constant the server wants set to allow players to use specific widgets buttons.
// 0 Allows all buttons. See ASSOCIATE_WIDGET_BUTTONS below for values needed to be
// added to block those buttons.
// Example: BTN_CMD_GHOST_MODE = 0x00000800; To remove you would put 2048 below.
// Since Hex 800 is Decimal 2048.
const int AI_DM_WIDGET_ACCESS_BUTTONS = 0;
// The constant the server wants set to allow players to use specific AI buttons.
// 0 Allows all buttons. See ASSOCIATE_AI_BUTTONS below for values needed to be
// added to block those buttons.
// Example: BTN_AI_MAGIC_LEVEL = 0x00000040; To remove you would put 64 below.
// Since Hex 40 is Decimal 64. Adding BTN_AI_LOOT = 0x00001000; to that would be
// 64 + 4096 = 4160 to Block Magic Level and Auto Looting.
const int AI_DM_AI_ACCESS_BUTTONS = 0;
//************************** CONVERSATION CONSTANTS **************************
// Player's can tell their associates to ignore enemy associates.
const int AI_IGNORE_ASSOCIATES_ON = TRUE;
// Associates with a Taunt skill higher than their level can be told to taunt.
const int AI_TAUNTING_ON = TRUE;
// Associates that cast spells can be told to use counterspell.
const int AI_COUNTERSPELLING_ON = TRUE;
// Associates with lore skill higher than the master can identify items.
const int AI_IDENTIFY_ON = TRUE;
// Associates can be called upon to scout ahead for monsters.
const int AI_SCOUT_AHEAD_ON = TRUE;
// A player can open a henchmen's inventory.
const int AI_OPEN_INVENTORY = TRUE;
// Allows players to have associates pickup loot.
const int AI_PICKUP_LOOT = TRUE;
// Allows players to remove a henchman.
const int AI_REMOVE_HENCHMAN_ON = FALSE;
//***************************** Health Constants *****************************
// % of health for when a creature is considered wounded.
const int AI_HEALTH_WOUNDED = 50;
// % of health when creature is considered badly wounded.
const int AI_HEALTH_BLOODY = 25;
//***************************** MORAL CONSTANTS ******************************
// Moral checks are only made once a creature is below AI_HEALTH_WOUNDED.
// The moral DC is AI_MORAL_DC - the number of Allies. Default: 5
const int AI_WOUNDED_MORAL_DC = 5;
// Once a creature goes below AI_HEALTHY_BLOODY then it uses this moral DC. Default: 15
const int AI_BLOODY_MORAL_DC = 15;
//******************************* WINDOW CONSTANTS *****************************
const string AI_MAIN_NUI = "ai_main_nui";
const string AI_COMMAND_NUI = "_command_nui";
const string AI_NUI = "_ai_nui";
const string AI_WIDGET_NUI = "_widget_nui";
const string AI_LOOTFILTER_NUI = "_lootfilter_nui";
const string AI_COPY_NUI = "_copy_nui";
const string AI_PLUGIN_NUI = "ai_plugin_nui";
const string AI_QUICK_WIDGET_NUI = "_quick_widget_nui";
const string AI_SPELL_MEMORIZE_NUI = "_spell_memorize_nui";
const string AI_SPELL_KNOWN_NUI = "_spell_known_nui";
const string AI_SPELL_DESCRIPTION_NUI = "ai_spell_desc_nui";
const string AI_EFFECT_ICON_NUI = "ai_effect_icon_nui";
//******************************* CORE CONSTANTS *******************************
// The following constants are core constants and changing any of these without
// understanding the whole system could cause unforseen results.
// CHANGE AT YOUR OWN RISK.
// Variable used to asave a monster object for changing.
const string AI_MONSTER_OBJECT = "AI_MONSTER_OBJECT";
// Variable used to save a monsters json for changing.
const string AI_MONSTER_JSON = "AI_MONSTER_JSON";
// Variable used to let PEPS know that a monster plugin changed the monster.
const string AI_MONSTER_CHANGED = "AI_MONSTER_CHANGED";
// Variable used to save an associates class list to change known list json.
const string AI_CLASS_LIST_JSON = "AI_CLASS_LIST_JSON";
// Startup variable to tell plugins that we have started.
const string AI_STARTING_UP = "AI_STARTING_UP";
// Add plugin variable to tell plugins that we are adding them to PEPS.
const string AI_ADD_PLUGIN = "AI_ADD_PLUGIN";
// Startup variable to tell plugins what json array to add their plugin to.
const string AI_JSON_PLUGINS = "AI_JSON_PLUGINS";
// Plugin variable to have plugins return if they setup the plugin in the json for PEPS.
const string AI_PLUGIN_SET = "AI_PLUGIN_SET";
// Monster modification variable to let PEPS know what mods are available.
const string AI_MONSTER_MOD_JSON = "AI_MONSTER_MOD_JSON";
// The maximum number of henchman the code works with.
const int AI_MAX_HENCHMAN = 12;
// Delay between Henchman casting Healing spells. Must be minimum of 0.5 seconds.
const float AI_HENCHMAN_HEALING_DELAY = 6.0;
// A variable that can be set on creatures to stop mobile animations.
const string AI_NO_ANIMATION = "AI_NO_ANIMATION";
// How many seconds in a combat round.
const int AI_COMBAT_ROUND_IN_SECONDS = 6;
// Used for actions that take x seconds but don't have an action constant.
const string AI_COMBAT_WAIT_IN_SECONDS = "AI_COMBAT_WAIT_IN_SECONDS";
// Constants used to define the difficulty of the battle for associates.
// 20+ : Impossible - Cannot win.
// 17 to 19 : Overpowering - Use all of our powers.
// 15 to 16 : Very Difficult - Use all of our power (Highest level spells).
// 11 to 14 : Challenging - Use most of our power (Higher level powers).
// 8 to 10 : Moderate - Use half of our power (Mid level powers and less).
// 5 to 7 : Easy - Use our weaker powers (Lowest level powers).
// 2 to 4 : Effortless - Don't waste spells and powers on this.
// 1 or less: Pointless - We probably should ignore these dangers.
const int AI_COMBAT_IMPOSSIBLE = 21;
const int AI_COMBAT_OVERPOWERING = 17;
const int AI_COMBAT_VERY_DIFFICULT = 15;
const int AI_COMBAT_CHALLENGING = 11;
const int AI_COMBAT_MODERATE = 10;
const int AI_COMBAT_EASY = 7;
const int AI_COMBAT_EFFORTLESS = 4;
// Variables used to keep track of enemies in combat.
const string AI_ENEMY = "AI_ENEMY"; // The enemy objects.
const string AI_ENEMY_DISABLED = "AI_ENEMY_DISABLED"; // Int if they are disabled.
const string AI_ENEMY_PERCEIVED = "AI_ENEMY_PERCEIVED"; // TRUE if we have seen or heard them, FALSE if not.
const string AI_ENEMY_RANGE = "AI_ENEMY_RANGE"; // The range from OBJECT_SELF.
const string AI_ENEMY_COMBAT = "AI_ENEMY_COMBAT"; // Combat rating: (BAB + AC - 10) / 2
const string AI_ENEMY_MELEE = "AI_ENEMY_MELEE"; // Enemies within 5 meters - Allies within 5 meters.
const string AI_ENEMY_HEALTH = "AI_ENEMY_HEALTH"; // % of hitpoints.
const string AI_ENEMY_NUMBERS = "AI_ENEMY_NUM"; // Number of enemies in combat.
const string AI_ENEMY_POWER = "AI_ENEMY_POWER"; // (Level * Health %) / 100 added for each enemy to this.
const string AI_ENEMY_NEAREST = "AI_ENEMY_NEAREST"; // Nearest enemy to OBJECT_SELF.
// Variables used to keep track of allies in combat.
const string AI_ALLY = "AI_ALLY"; // All friendly creatures
const string AI_ALLY_DISABLED = "AI_ALLY_DISABLED"; // Int if they are disabled.
const string AI_ALLY_PERCEIVED = "AI_ALLY_PERCEIVED"; // All allies are set to be seen and heard.
const string AI_ALLY_RANGE = "AI_ALLY_RANGE"; // The range from OBJECT_SELF.
const string AI_ALLY_COMBAT = "AI_ALLY_COMBAT"; // Combat rating: (BAB + AC - 10) / 2
const string AI_ALLY_MELEE = "AI_ALLY_MELEE"; // Enemies within 5 meters - Allies within 5 meters.
const string AI_ALLY_HEALTH = "AI_ALLY_HEALTH"; // % of hitpoints.
const string AI_ALLY_NUMBERS = "AI_ALLY_NUM"; // Number of allies in combat.
const string AI_ALLY_POWER = "AI_ALLY_POWER"; // (Level * Health %) / 100 added for each enemy to this.
// Variable name used to define the ai scripts being used by creatures.
const string AI_DEFAULT_SCRIPT = "AI_DEFAULT_SCRIPT";
const string AI_COMBAT_SCRIPT = "AI_COMBAT_SCRIPT";
// Constants used in a creatures listening patterns.
const string AI_I_SEE_AN_ENEMY = "AI_I_SEE_AN_ENEMY";
const string AI_I_HEARD_AN_ENEMY = "AI_I_HEARD_AN_ENEMY";
const string AI_ATKED_BY_WEAPON = "AI_ATK_BY_WEAPON";
const string AI_ATKED_BY_SPELL = "AI_ATK_BY_SPELL";
const string AI_I_AM_WOUNDED = "AI_I_AM_WOUNDED";
const string AI_I_AM_DEAD = "AI_I_AM_DEAD";
const string AI_I_AM_DISEASED = "AI_I_AM_DISEASED";
const string AI_I_AM_POISONED = "AI_I_AM_POISONED";
const string AI_I_AM_WEAK = "AI_I_AM_WEAK";
const int AI_ALLY_SEES_AN_ENEMY = 1;
const int AI_ALLY_HEARD_AN_ENEMY = 2;
const int AI_ALLY_ATKED_BY_WEAPON = 3;
const int AI_ALLY_ATKED_BY_SPELL = 4;
const int AI_ALLY_IS_WOUNDED = 5;
const int AI_ALLY_IS_DEAD = 6;
const int AI_ALLY_IS_DISEASED = 7;
const int AI_ALLY_IS_POISONED = 8;
const int AI_ALLY_IS_WEAK = 9;
const string AI_MY_TARGET = "AI_MY_TARGET";
// Constant used by monsters to reduce checks while searching for unseen targets.
const string AI_AM_I_SEARCHING = "AI_AM_I_SEARCHING";
// Used to keep track of oCreature attempting to hide.
const string AI_TRIED_TO_HIDE = "AI_TRIED_TO_HIDE";
// Constant used by creatures to keep track of invisible creatures.
const string AI_IS_INVISIBLE = "AI_IS_INVISIBLE";
// Constants used in combat to keep track of a creatures last action.
// 0+ is the last spell cast from the line number in Spells.2da.
const string sLastActionVarname = "AI_LAST_ACTION";
const int AI_LAST_ACTION_CAST_SPELL = -1;
const int AI_LAST_ACTION_NONE = -2;
const int AI_LAST_ACTION_MELEE_ATK = -3;
const int AI_LAST_ACTION_RANGED_ATK = -4;
const int AI_LAST_ACTION_USED_FEAT = -5;
const int AI_LAST_ACTION_USED_ITEM = -6;
const int AI_LAST_ACTION_USED_SKILL = -7;
const int AI_LAST_ACTION_MOVE = -8;
// Variable name used to keep track of Action Modes.
const string AI_CURRENT_ACTION_MODE = "AI_CURRENT_ACTION_MODE";
// Variable name used to keep track of object usage by the AI.
const string AI_OBJECT_IN_USE = "AI_OBJECT_IN_USE";
// Variable name used to keep a creatures attacked targets.
const string AI_ATTACKED_PHYSICAL = "AI_ATTACKED_PHYSICAL";
const string AI_ATTACKED_SPELL = "AI_ATTACKED_SPELL";
// Variable name used to keep track of a creatures normal polymorph form.
const string AI_NORMAL_FORM = "AI_NORMAL_FORM";
// Variable name used to keep track if a creature has been buffed yet.
const string AI_CASTER_BUFFS_SET = "AI_CASTER_BUFFS_SET";
// Variable name used to keep track of rounds in combat for a custom ai script.
const string AI_ROUND = "AI_ROUND";
// Combat Ranges
const float AI_RANGE_MELEE = 5.0f; // Anyone within this is considered to be in melee.
const float AI_RANGE_CLOSE = 8.0f; // For anything requiring to be within 30'.
const float AI_RANGE_LONG = 15.0f; // Mainly used for distance ranged attacks.
const float AI_RANGE_PERCEPTION = 35.0f; // This is the distance for perception in battle.
const float AI_RANGE_BATTLEFIELD = 40.0f; // This is the size of the battlefield area.
// Spell ranges.
const float AI_SHORT_DISTANCE = 8.0f;
const float AI_MEDIUM_DISTANCE = 20.0f;
const float AI_LONG_DISTANCE = 40.0f;
// When computer checks if a creature should cast a specific spell at a target.
// Computer makes a spell check vs the targets saving throw.
// Spell check roll for the caster is
// [Innate spell Level + Random (AI_SPELL_CHECK_DIE) + AI_SPELL_CHECK_BONUS]
// If the spell gives a save for half (i.e. FireBall) and the target does not have
// Evasion then they get an additional bonus of AI_SPELL_CHECK_NO_EVASION_BONUS.
const int AI_SPELL_CHECK_DIE = 6;
const int AI_SPELL_CHECK_BONUS = 3;
const int AI_SPELL_CHECK_NO_EVASION_BONUS = 10;
// When the computer checks if a creature should use defensive casting it looks
// at the spell level + AI_DEFENSIVE_CASTING_DC vs casters concentration
// and feat bonuses (i.e. COMBAT_CASTING) + Random (AI_DEFENSIVE_CASTING_ROLL).
const int AI_DEFENSIVE_CASTING_DC = 19; // 19 will allow them to use it at 50% effectiveness.
const int AI_DEFENSIVE_CASTING_DIE = 10;
// When the computer checks to see if it should cast in melee combat it looks
// at CASTING_IN_MELEE_DC + SpellLevel + (Num of creatures in melee * GetHitDice (NearestEnemy));
// vs the casters concentration + Random (AI_CASTING_IN_MELEE_ROLL).
const int AI_CASTING_IN_MELEE_DC = 10;
const int AI_CASTING_IN_MELEE_ROLL = 10;
// For getting a specific class the following constants were added to flesh out
// the CLASS_TYPE_*
const int AI_CLASS_TYPE_CASTER = -1;
const int AI_CLASS_TYPE_DIVINE = -2;
const int AI_CLASS_TYPE_ARCANE = -3;
const int AI_CLASS_TYPE_WARRIOR = -4;
// For getting a specific race the following constants were added to flesh out
// the RACIAL_TYPE_*
const int AI_RACIAL_TYPE_ANIMAL_BEAST = -1;
const int AI_RACIAL_TYPE_HUMANOID = -2;
// Bitwise constants for negative conditions we might want to try to cure
const int AI_CONDITION_POISON = 0x00000001;
const int AI_CONDITION_DISEASE = 0x00000002;
const int AI_CONDITION_BLINDDEAF = 0x00000004;
const int AI_CONDITION_ATK_DECREASE = 0x00000008;
const int AI_CONDITION_DMG_DECREASE = 0x00000010;
const int AI_CONDITION_DMG_I_DECREASE = 0x00000020;
const int AI_CONDITION_SKILL_DECREASE = 0x00000040;
const int AI_CONDITION_SAVE_DECREASE = 0x00000080;
const int AI_CONDITION_SR_DECREASE = 0x00000100;
const int AI_CONDITION_AC_DECREASE = 0x00000200;
const int AI_CONDITION_SLOW = 0x00000400;
const int AI_CONDITION_ABILITY_DRAIN = 0x00000800;
const int AI_CONDITION_LEVEL_DRAIN = 0x00001000;
const int AI_CONDITION_CHARMED = 0x00002000;
const int AI_CONDITION_DAZED = 0x00004000;
const int AI_CONDITION_STUNNED = 0x00008000;
const int AI_CONDITION_FRIGHTENED = 0x00010000;
const int AI_CONDITION_CONFUSED = 0x00020000;
const int AI_CONDITION_CURSE = 0x00040000;
const int AI_CONDITION_PARALYZE = 0x00080000;
const int AI_CONDITION_DOMINATED = 0x00100000;
// Database constants for Associate modes.
const string AI_MODE_DB_TABLE = "AI_MODE_DB_TABLE";
// Bitwise constants for Associate modes that are used with Get/SetAssociateMode().
const string sAIModeVarname = "ASSOCIATE_MODES";
//const int AI_MODE_DISTANCE_CLOSE = 0x00000001; // Stays within AI_DISTANCE_CLOSE of master.
//const int AI_MODE_DISTANCE_MEDIUM = 0x00000002; // Stays within AI_DISTANCE_MEDIUM of master.
const int AI_MODE_ACTION_GHOST = 0x00000004; // Defines if the player is using Ghost mode when using associate actions.
const int AI_MODE_SELF_HEALING_OFF = 0x00000008; // Creature will not use healing items or spells on self.
const int AI_MODE_PARTY_HEALING_OFF = 0x00000010; // Creature will not use healing items or spells on party.
const int AI_MODE_GHOST = 0x00000020; // Creature can move through other creatures.
const int AI_MODE_OPEN_DOORS = 0x00000040; // Creature will attempted to open all doors.
const int AI_MODE_EQUIP_WEAPON_OFF = 0x00000080; // The AI will not equip weapons.
const int AI_MODE_BASH_LOCKS = 0x00000100; // Will bash locks if cannot open door/placeable.
const int AI_MODE_AGGRESSIVE_SEARCH = 0x00000200; // Sets associate to continuous search mode.
const int AI_MODE_AGGRESSIVE_STEALTH = 0x00000400; // Sets associate to continuous stealth mode.
const int AI_MODE_PICK_LOCKS = 0x00000800; // Will pick locks if possible.
const int AI_MODE_DISARM_TRAPS = 0x00001000; // Will disarm traps.
const int AI_MODE_SCOUT_AHEAD = 0x00002000; // Will move ahead of master and scout.
const int AI_MODE_DEFEND_MASTER = 0x00004000; // Will attack enemies attacking our master.
const int AI_MODE_STAND_GROUND = 0x00008000; // Will stay in one place until new command.
const int AI_MODE_STOP_RANGED = 0x00010000; // Will not use ranged weapons.
const int AI_MODE_FOLLOW = 0x00020000; // Keeps associate following master ignoring combat.
const int AI_MODE_PICKUP_ITEMS = 0x00040000; // Will pickup up all items for master.
const int AI_MODE_COMMANDED = 0x00080000; // In Command mode then don't follow, search, etc.
const int AI_MODE_IGNORE_TRAPS = 0x00100000; // Creature will ignore traps on the floor.
const int AI_MODE_NO_STEALTH = 0x00200000; // Will not cast invisibilty or use stealth.
const int AI_MODE_DO_NOT_SPEAK = 0x00400000; // Tells the henchmen to be silent and not talk.
const int AI_MODE_CHECK_ATTACK = 0x00800000; // Will only engage in combats they think they can win.
const int AI_MODE_IGNORE_ASSOCIATES = 0x01000000; // Will ignore associates in combat.
//const int AI_MODE_ = 0x02000000; // Not used.
//const int AI_MODE_ = 0x04000000; // Not used.
//const int AI_MODE_ = 0x08000000; // Not used.
//const int AI_MODE_ = 0x10000000; // Not used.
//const int AI_MODE_ = 0x20000000; // Not used.
//const int AI_MODE_ = 0x40000000; // Not used.
//const int AI_MODE_ = 0x80000000; // Not used.
// Bitwise constants for Associate magic modes that are used with Get/SetAssociateMagicMode().
const string sMagicModeVarname = "ASSOCIATE_MAGIC_MODES";
const int AI_MAGIC_BUFF_MASTER = 0x00000001; // Buffs master before other allies.
const int AI_MAGIC_NO_MAGIC = 0x00000002; // Will not use any magic (Spells, abilities).
const int AI_MAGIC_DEFENSIVE_CASTING = 0x00000004; // Will only cast defensive spells.
const int AI_MAGIC_OFFENSIVE_CASTING = 0x00000008; // Will only cast offensive spells.
const int AI_MAGIC_STOP_DISPEL = 0x00000010; // Will not cast dispel type spells.
const int AI_MAGIC_BUFF_AFTER_REST = 0x00000020; // Will buff the party after resting.
const int AI_MAGIC_NO_MAGIC_ITEMS = 0x00000040; // Will not use magic items in combat.
const int AI_MAGIC_CURE_SPELLS_OFF = 0x00000080; // Will not cast cure spells.
const int AI_MAGIC_EFFECT_ICON_REPORT = 0x00000100; // Sets each player to report Effect Icons to chat.
//const int = 0x00000200; // Not used.
//const int = 0x00000400; // Not used.
const int AI_MAGIC_NO_SPONTANEOUS_CURE = 0x00000800; // Caster will stop using spontaneous cure spells.
//const int AI_MAGIC_ = 0x00001000; // Not used.
//const int AI_MAGIC_ = 0x00002000; // Not used.
//const int AI_MAGIC_ = 0x00004000; // Not used.
//const int AI_MAGIC_ = 0x00008000; // Not used.
//const int AI_MAGIC_ = 0x00010000; // Not used.
//const int AI_MAGIC_ = 0x00020000; // Not used.
//const int AI_MAGIC_ = 0x00040000; // Not used.
//const int AI_MAGIC_ = 0x00080000; // Not used.
//const int AI_MAGIC_ = 0x00100000; // Not used.
//const int AI_MAGIC_ = 0x00200000; // Not used.
//const int AI_MAGIC_ = 0x00400000; // Not used.
//const int AI_MAGIC_ = 0x00800000; // Not used.
//const int AI_MAGIC_ = 0x01000000; // Not used.
//const int AI_MAGIC_ = 0x02000000; // Not used.
//const int AI_MAGIC_ = 0x04000000; // Not used.
//const int AI_MAGIC_ = 0x08000000; // Not used.
//const int AI_MAGIC_ = 0x10000000; // Not used.
//const int AI_MAGIC_ = 0x20000000; // Not used.
//const int AI_MAGIC_ = 0x40000000; // Not used.
//const int AI_MAGIC_ = 0x80000000; // Not used.
// Use by NUI windows to stop saving move states while loading.
const string AI_NO_NUI_SAVE = "AI_NO_NUI_SAVE";
// Bitwise menu constants for Widget buttons that are used with Get/SetAssociateWidgetButtons().
const string sWidgetButtonsVarname = "ASSOCIATE_WIDGET_BUTTONS";
const int BTN_WIDGET_OFF = 0x00000001; // Removes the widget from the screen, For PC it removes all associates.
const int BTN_WIDGET_LOCK = 0x00000002; // Locks the widget to the current coordinates.
const int BTN_CMD_GUARD = 0x00000004; // Command associates to Guard Me. PC widget only.
const int BTN_CMD_FOLLOW = 0x00000008; // Command associates to Follow. PC widget only.
const int BTN_CMD_HOLD = 0x00000010; // Command associates to Stand Ground. PC widget only.
const int BTN_CMD_ATTACK = 0x00000020; // Command associates to Attack Nearest. PC widget only.
const int BTN_BUFF_REST = 0x00000040; // Buffs with long duration spells after resting. Associate widget only.
const int BTN_BUFF_SHORT = 0x00000080; // Buffs with short duration spells.
const int BTN_BUFF_LONG = 0x00000100; // Buffs with long duration spells.
const int BTN_BUFF_ALL = 0x00000200; // Buffs with all spells.
const int BTN_CMD_ACTION = 0x00000400; // Command associate to do an action.
const int BTN_CMD_GHOST_MODE = 0x00000800; // Toggle's associates ghost mode.
const int BTN_CMD_AI_SCRIPT = 0x00001000; // Toggle's special tactics ai scripts.
const int BTN_CMD_PLACE_TRAP = 0x00002000; // A trapper may place traps.
const int BTN_CMD_CAMERA = 0x00004000; // Places camera view on associate.
const int BTN_CMD_INVENTORY = 0x00008000; // Opens inventory of associate.
const int BTN_CMD_FAMILIAR = 0x00010000; // Summons familiar.
const int BTN_CMD_COMPANION = 0x00020000; // Summons Companion.
const int BTN_CMD_SEARCH = 0x00040000; // Command all associates to use search mode. PC widget only.
const int BTN_CMD_STEALTH = 0x00080000; // Command all associates to use stealth mode. PC widget only.
const int BTN_CMD_SCOUT = 0x00100000; // Command associate to scout ahead of the part.
const int BTN_CMD_SPELL_WIDGET = 0x00200000; // Allows adding or removing spells from Spell Widget.
const int BTN_CMD_JUMP_TO = 0x00400000; // Player can make associates jump to them.
const int BTN_WIDGET_VERTICAL = 0x80000000; // Widget will be displayed vertical.
// Bitwise menu constants for Associate AI buttons that are used with Get/SetAssociateAIButtons().
const string sAIButtonsVarname = "ASSOCIATE_AI_BUTTONS";
const int BTN_AI_FOR_PC = 0x00000001; // PC use AI. PC widget only.
const int BTN_AI_USE_RANGED = 0x00000002; // AI uses ranged attacks.
const int BTN_AI_USE_SEARCH = 0x00000004; // AI uses Search.
const int BTN_AI_USE_STEALTH = 0x00000008; // AI uses Stealth.
const int BTN_AI_REMOVE_TRAPS = 0x00000010; // AI seeks out and removes traps.
const int BTN_AI_PICK_LOCKS = 0x00000020; // AI will attempt to pick locks.
const int BTN_AI_MAGIC_LEVEL = 0x00000040; // Increase chance to use magic in battle.
const int BTN_AI_NO_SPONTANEOUS = 0x00000080; // Stops the use of spontaneous spells.
const int BTN_AI_NO_MAGIC_USE = 0x00000100; // Will not use magic in battle.
const int BTN_AI_NO_MAGIC_ITEM_USE = 0x00000200; // Will not use magic items in battle.
const int BTN_AI_DEF_MAGIC_USE = 0x00000400; // Will use Defensive spells only in battle.
const int BTN_AI_OFF_MAGIC_USE = 0x00000800; // Will use Offensive spells only in battle.
const int BTN_AI_LOOT = 0x00001000; // Auto picking up loot on/off.
const int BTN_AI_FOLLOW_TARGET = 0x00002000; // Selects a target to follow.
const int BTN_AI_HEAL_OUT = 0x00004000; // Increase minimum hp required before ai heals out of combat.
const int BTN_AI_PERC_RANGE = 0x00008000; // Adjust the perception range of the henchman.
const int BTN_AI_HEAL_IN = 0x00010000; // Increase minimum hp required before ai heals in combat.
const int BTN_AI_OPEN_DOORS = 0x00020000; // AI will open all closed doors.
const int BTN_AI_STOP_SELF_HEALING = 0x00040000; // Stops AI from using any healing on self.
const int BTN_AI_STOP_PARTY_HEALING = 0x00080000; // Stops AI from using any healing on party.
const int BTN_AI_IGNORE_ASSOCIATES = 0x00100000; // AI will deprioritize enemy associates.
const int BTN_AI_STOP_CURE_SPELLS = 0x00200000; // AI uses cure spells.
const int BTN_AI_STOP_WEAPON_EQUIP = 0x00400000; // AI can equip different weapons.
const int BTN_AI_IGNORE_TRAPS = 0x00800000; // AI will ignore traps on the floor.
//const int BTN_AI = 0x01000000; // Not used.
//const int BTN_AI = 0x02000000; // Not used.
const int BTN_AI_BASH_LOCKS = 0x04000000; // AI will attempt to bash any locks they can't get past.
const int BTN_AI_REDUCE_SPEECH = 0x08000000; // Reduce the associates speaking.
// Bitwise menu constants for DM access for players Widget buttons uses BTN_CMD and BTN_BUFF bitwise see above.
const string sDMWidgetAccessVarname = "AI_RULES_WIDGET_BUTTONS_ACCESS";
// Bitwise menu constants for DM access for players AI buttons uses BTN_AI bitwise see above.
const string sDMAIAccessVarname = "AI_RULES_AI_BUTTONS_ACCESS";
// Variable name for DM widget buttons.
const string sDMWidgetButtonVarname = "DM_WIDGET_BUTTONS";
// DM Widget buttons states.
const int BTN_DM_WIDGET_OFF = 0x00000001; // Removes the widget from the screen, For PC it removes all associates.
const int BTN_DM_WIDGET_LOCK = 0x00000002; // Locks the widget to the current coordinates.
const int BTN_DM_CMD_GROUP1 = 0x00000004; // Does all the group 1 commands.
const int BTN_DM_CMD_GROUP2 = 0x00000008; // Does all the group 2 commands.
const int BTN_DM_CMD_GROUP3 = 0x00000010; // Does all the group 3 commands.
const int BTN_DM_CMD_GROUP4 = 0x00000020; // Does all the group 4 commands.
const int BTN_DM_CMD_GROUP5 = 0x00000040; // Does all the group 5 commands.
const int BTN_DM_CMD_GROUP6 = 0x00000080; // Does all the group 6 commands.
const int BTN_DM_CMD_CAMERA = 0x00000100; // Selects new object to hold the camera view.
const int BTN_DM_CMD_INVENTORY = 0x00000200; // Selects a creature to open the inventory of.
const int BTN_DM_CMD_MEMORIZE = 0x00000400; // Allows associate to change memorized spells.
// Bitwise constants for Associate loot options that are used with Get/SetAssociateLootMode().
const string sLootFilterVarname = "ASSOCIATE_LOOT_MODES";
const int AI_LOOT_PLOT = 0x00000001;
const int AI_LOOT_WEAPONS = 0x00000002;
const int AI_LOOT_ARMOR = 0x00000004;
const int AI_LOOT_SHIELDS = 0x00000008;
const int AI_LOOT_HEADGEAR = 0x00000010;
const int AI_LOOT_BELTS = 0x00000020;
const int AI_LOOT_BOOTS = 0x00000040;
const int AI_LOOT_CLOAKS = 0x00000080;
const int AI_LOOT_GLOVES = 0x00000100;
const int AI_LOOT_JEWELRY = 0x00000200;
const int AI_LOOT_POTIONS = 0x00000400;
const int AI_LOOT_SCROLLS = 0x00000800;
const int AI_LOOT_WANDS_RODS_STAVES = 0x00001000;
const int AI_LOOT_GEMS = 0x00002000;
const int AI_LOOT_MISC = 0x00004000;
const int AI_LOOT_ARROWS = 0x00008000;
const int AI_LOOT_BOLTS = 0x00010000;
const int AI_LOOT_BULLETS = 0x00020000;
const int AI_LOOT_GIVE_TO_PC = 0x80000000;
// Default value for all loot filters to be on.
const int AI_LOOT_ALL_ON = 262143;
// Variable to keep track of who is in ghost mode.
const string sGhostModeVarname = "AI_GHOST_MODE_ON";
// Variables for gold piece value to pickup items.
const string AI_MIN_GOLD_ = "AI_MIN_GOLD_";
// Variable used to limit the spamming of NUI buttons.
const string AI_DELAY_NUI_USE = "AI_DELAY_NUI_USE";
// Variable for maximum weight to pickup from looting.
const string AI_MAX_LOOT_WEIGHT = "AI_MAX_LOOT_WEIGHT";
// Variable to change the size of the widget buttons.
const string AI_WIDGET_BUTTON_SIZE = "AI_WIDGET_BUTTON_SIZE";
// Variable to change the difficulty so a player can adjust spell usage.
const string AI_DIFFICULTY_ADJUSTMENT = "AI_DIFFICULTY_ADJUSTMENT";
// Variable to change the Healing % limit for out of combat.
const string AI_HEAL_OUT_OF_COMBAT_LIMIT = "AI_HEAL_OUT_OF_COMBAT_LIMIT";
// Variable to change the Healing % limit for in combat.
const string AI_HEAL_IN_COMBAT_LIMIT = "AI_HEAL_IN_COMBAT_LIMIT";
// Variable to change the looting range.
const string AI_LOOT_CHECK_RANGE = "AI_LOOT_CHECK_RANGE";
// Variable to change the lock checking range.
const string AI_LOCK_CHECK_RANGE = "AI_LOCK_CHECK_RANGE";
// Variable to change the trap checking range.
const string AI_TRAP_CHECK_RANGE = "AI_TRAP_CHECK_RANGE";
// Variable to change the range an associate follows the pc.
const string AI_FOLLOW_RANGE = "AI_FOLLOW_RANGE";
// Variable that holds the target for an associate to follow.
const string AI_FOLLOW_TARGET = "AI_FOLLOW_TARGET";
// Variable that holds the perception range of associates i.e. 8, 9, 10, 11.
const string AI_ASSOCIATE_PERCEPTION = "AI_PERCEPTION_RANGE";
// Variable that holds the perception distance of associates i.e. 30.0 meters.
const string AI_ASSOC_PERCEPTION_DISTANCE = "AI_ASSOC_PERCEPTION_DISTANCE";
// Variable that holds the open doors range of the henchman.
const string AI_OPEN_DOORS_RANGE = "AI_OPEN_DOORS_RANGE";
// Variable that holds the Spell widgets json data.
const string AI_SPELLS_WIDGET = "AI_SPELLS_WIDGET";
// The number of Buff Groups
const int AI_BUFF_GROUPS = -17;
// Variable name used to keep track if we have set our talents.
const string AI_TALENTS_SET = "AI_TALENTS_SET";
// New talent categories
const string AI_TALENT_ENHANCEMENT = "E";
const string AI_TALENT_PROTECTION = "P";
const string AI_TALENT_SUMMON = "S";
const string AI_TALENT_HEALING = "H";
const string AI_TALENT_CURE = "C";
const string AI_TALENT_INDISCRIMINANT_AOE = "I";
const string AI_TALENT_DISCRIMINANT_AOE = "D";
const string AI_TALENT_RANGED = "R";
const string AI_TALENT_TOUCH = "T";
// Talent types.
const int AI_TALENT_TYPE_SPELL = 1;
const int AI_TALENT_TYPE_SP_ABILITY = 2;
const int AI_TALENT_TYPE_FEAT = 3;
const int AI_TALENT_TYPE_ITEM = 4;
// Variable name used to have associates fight the pc's selected target.
const string AI_PC_LOCKED_TARGET = "AI_PC_LOCKED_TARGET";
// Variable name of json talent immunity.
const string AI_TALENT_IMMUNITY = "AI_TALENT_IMMUNITY";
// Variables keeps track of the maximum level for the talent category.
const string AI_MAX_TALENT = "AI_MAX_TALENT_";
// Backward compatability constants.
const int X2_EVENT_CONCENTRATION_BROKEN = 12400;
// Variable set on the module if the module is using PRC.
const string AI_USING_PRC = "AI_USING_PRC";
// Variable that sets if the rules have been added to the module.
const string AI_RULES_SET = "AI_RULES_SET";
// Variable that tells us that oCreature has run our OnSpawn event.
const string AI_ONSPAWN_EVENT = "AI_ONSPAWN_EVENT";
// Variable used to define a creatures unique Tag for widgets.
const string AI_TAG = "AI_TAG";
// Variable that saves any module target event script so we can pass it along.
const string AI_MODULE_TARGET_EVENT = "AI_MODULE_TARGET_EVENT";
// Variable for plugins to inject Targeting mode code into PEPS.
const string AI_PLUGIN_TARGET_SCRIPT = "AI_PLUGIN_TARGET_SCRIPT";
// Variable for PEPS to inject effect icons NUI information.
const string AI_MODULE_GUI_EVENT = "AI_MODULE_GUI_EVENT";
// Variable used on the player to define the targeting action in the OnPlayerTarget event script.
const string AI_TARGET_MODE = "AI_TARGET_MODE";
// Variable used on the player to define which associate triggered the OnPlayer Target.
const string AI_TARGET_ASSOCIATE = "AI_TARGET_ASSOCIATE";
// Bitwise constants for immune damage item properties that is used with Get/SetItemProperty().
const string sIPImmuneVarname = "AI_IP_IMMUNE";
// Bitwise constants for resisted damage item properties that is used with Get/SetItemProperty().
const string sIPResistVarname = "AI_IP_RESIST";
// Variable name for the Int constant for reduced damage item property set to the bonus of the weapon required.
const string sIPReducedVarname = "AI_IP_REDUCED";
// Variable name for the Int (Bool) constant for the haste item property.
const string sIPHasHasteVarname = "AI_IP_HAS_HASTE";
// Variable name used to hold the party xp base needed to adjust party xp.
const string AI_BASE_PARTY_SCALE_XP = "AI_BASE_PARTY_SCALE_XP";
//***************************** AI RULES CONSTANTS *****************************
// Variable name set to a creatures full name to set debugging on.
const string AI_RULE_DEBUG_CREATURE = "AI_RULE_DEBUG_CREATURE";
// Moral checks on or off.
const string AI_RULE_MORAL_CHECKS = "AI_RULE_MORAL_CHECKS";
// Allows monsters to prebuff before combat starts.
const string AI_RULE_BUFF_MONSTERS = "AI_RULE_BUFF_MONSTERS";
// Allows monsters to use the ambush AI scripts.
const string AI_RULE_AMBUSH = "AI_RULE_AMBUSH";
// Enemies may summon familiars and Animal companions and will be randomized.
const string AI_RULE_SUMMON_COMPANIONS = "AI_RULE_SUMMON_COMPANIONS";
// Allows monsters cast summons spells when prebuffing.
const string AI_RULE_PRESUMMON = "AI_RULE_PRESUMMON";
// Allow the AI move during combat base on the situation and action taking.
const string AI_RULE_ADVANCED_MOVEMENT = "AI_RULE_ADVANCED_MOVEMENT";
// Follow Item Level Restrictions for monsters/associates.
// Usually off in Single player and on in Multi player.
const string AI_RULE_ILR = "AI_RULE_ILR";
// Allow the AI to use Use Magic Device.
const string AI_RULE_ALLOW_UMD = "AI_RULE_ALLOW_UMD";
// Allow the AI to use healing kits.
const string AI_RULE_HEALERSKITS = "AI_RULE_HEALERSKITS";
// Summoned associates are permanent and don't disappear when the caster dies.
const string AI_RULE_PERM_ASSOC = "AI_RULE_PERM_ASSOC";
// Monster AI's chance to attack the weakest target instead of the nearest.
const string AI_RULE_AI_DIFFICULTY = "AI_RULE_AI_DIFFICULTY";
// Variable that can change the distance creatures will come and attack after
// hearing a shout from an ally that sees or hears an enemy.
// Or when searching for an invisible, heard enemy.
// 10.0 Short, 30.0 Average, 40.0 Long, 60.0 Huge.
const string AI_RULE_PERCEPTION_DISTANCE = "AI_RULE_PERCEPTION_DISTANCE";
// Enemy corpses remain on the floor instead of dissappearing.
const string AI_RULE_CORPSES_STAY = "AI_RULE_CORPSES_STAY";
// Monsters will wander around when not in combat.
const string AI_RULE_WANDER = "AI_RULE_WANDER";
// Increase the number of encounter creatures.
const string AI_INCREASE_ENC_MONSTERS = "AI_INCREASE_ENC_MONSTERS";
// Increase all monsters hitpoints by this percentage.
const string AI_INCREASE_MONSTERS_HP = "AI_INCREASE_MONSTERS_HP";
// Variable that can change the distance monsters can hear and see.
const string AI_RULE_MON_PERC_DISTANCE = "AI_RULE_MON_PERC_DISTANCE";
// Variable name set to hold the maximum number of henchman the player wants.
const string AI_RULE_MAX_HENCHMAN = "AI_RULE_MAX_HENCHMAN";
// Variable name set to hold the distance monsters can wander away.
const string AI_RULE_WANDER_DISTANCE = "AI_RULE_WANDER_DISTANCE";
// Variable name set to allow wandering monsters to open doors.
const string AI_RULE_OPEN_DOORS = "AI_RULE_OPEN_DOORS";
// Variable name set to hold the modules default xp scale for use later.
const string AI_RULE_DEFAULT_XP_SCALE = "AI_RULE_DEFAULT_XP_SCALE";
// Variable name set to allow the game to regulate experience based on party size.
const string AI_RULE_PARTY_SCALE = "AI_RULE_PARTY_SCALE";
// Variable name set to restrict the AI's use of Darkness.
const string AI_RULE_RESTRICTED_SPELLS = "AI_RULE_RESTRICTED_SPELLS";
/*/ Special behavior constants from x0_i0_behavior
const int NW_FLAG_BEHAVIOR_SPECIAL = 0x00000001;
//Will always attack regardless of faction
const int NW_FLAG_BEHAVIOR_CARNIVORE = 0x00000002;
//Will only attack if approached
const int NW_FLAG_BEHAVIOR_OMNIVORE = 0x00000004;
//Will never attack. Will alway flee.
const int NW_FLAG_BEHAVIOR_HERBIVORE = 0x00000008;
// This is the name of the local variable that holds the spawn-in conditions
const string sSpawnCondVarname = "NW_GENERIC_MASTER";
// The available spawn-in conditions from x0_i0_spawncond
const int NW_FLAG_ESCAPE_RETURN = 0x00000020; //Failed
const int NW_FLAG_ESCAPE_LEAVE = 0x00000040;
const int NW_FLAG_TELEPORT_RETURN = 0x00000080; //Failed
const int NW_FLAG_TELEPORT_LEAVE = 0x00000100;
const int NW_FLAG_END_COMBAT_ROUND_EVENT = 0x00004000;
const int NW_FLAG_ON_DIALOGUE_EVENT = 0x00008000;
const int NW_FLAG_AMBIENT_ANIMATIONS = 0x00080000;
const int NW_FLAG_HEARTBEAT_EVENT = 0x00100000;
const int NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS = 0x00200000;
const int NW_FLAG_DAY_NIGHT_POSTING = 0x00400000;
const int NW_FLAG_AMBIENT_ANIMATIONS_AVIAN = 0x00800000;
const string sWalkwayVarname = "NW_WALK_CONDITION";
// If set, the creature's waypoints have been initialized.
const int NW_WALK_FLAG_INITIALIZED = 0x00000001;
// If set, the creature will walk its waypoints constantly,
// moving on in each OnHeartbeat event. Otherwise,
// it will walk to the next only when triggered by an
// OnPerception event.
const int NW_WALK_FLAG_CONSTANT = 0x00000002;
// Set when the creature is walking day waypoints.
const int NW_WALK_FLAG_IS_DAY = 0x00000004;
// Set when the creature is walking back
const int NW_WALK_FLAG_BACKWARDS = 0x00000008;

File diff suppressed because it is too large Load Diff

1243
src/module/nss/0i_items.nss Normal file

File diff suppressed because it is too large Load Diff

1328
src/module/nss/0i_main.nss Normal file

File diff suppressed because it is too large Load Diff

4823
src/module/nss/0i_menus.nss Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: 0i_messages
//////////////////////////////////////////////////////////////////////////////////////////////////////
Include script for sending messages to files and players on the server.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_constants"
#include "0i_color"
// Sets up a Message on the module to be sent to the log and/or players.
// sTextColor color of text sent to the players and DM's.
// Use AI_COLOR_*. Where * is WHITE, RED, GREEN, BLUE, GRAY, or YELLOW.
// If nLog is TRUE it will send the message to the log file.
// If nToDMs is TRUE it will send the message to all DM's.
// If oPC is set to a player then they will get the message as well.
// Messages delivered by script should be colored as follows.
// _Debug message = COLOR_WHITE
// Generic messages for the player = AI_COLOR_YELLOW
// Negative messages for the player = AI_COLOR_RED
// Positive messages for the player = AI_COLOR_GREEN
// System messages, things that are not part of Dnd = COLOR_GRAY
// Descriptive in game messages = COLOR_BLUE
void ai_SendMessages(string sMessage, string sTextColor = AI_COLOR_YELLOW, object oPC = OBJECT_INVALID, int nToDMs = FALSE, int nLog = FALSE);
// Used for _debugging. Keeps all the information organized.
// Sends info to first pc if true and sends information to log file.
// sScriptName is the name of the script calling this function.
// sLineNumber is the line number of the code calling this function.
// sMessage is the description of the debug being sent.
void ai_Debug(string sScriptName, string sLineNumber, string sMessage);
// A counter to track microseconds in code. Start saves the counter.
void ai_Counter_Start();
// A counter to track microseconds in code. End displays the time between Start
// and End to the log file.
void ai_Counter_End(string sMessage = "");
void ai_SendMessages(string sMessage, string sTextColor = AI_COLOR_YELLOW, object oPC = OBJECT_INVALID, int nToDMs = FALSE, int nLog = FALSE)
{
// if nLog is TRUE send the message to the log file.
if(nLog)
{
sMessage = ai_StripColorCodes(sMessage);
// Add PC name to log to know who it belongs to.
string sLogPCName;
if(oPC != OBJECT_INVALID) sLogPCName = "(" + GetName(oPC) + ") ";
WriteTimestampedLogEntry("*** MESSAGE: " + sLogPCName + " " + sMessage);
}
sMessage = ai_AddColorToText(sMessage, sTextColor);
if(oPC != OBJECT_INVALID) SendMessageToPC(oPC, sMessage);
// If nToDMs is true send message to the DM's online.
if(nToDMs) SendMessageToAllDMs(sMessage);
}
void ai_Debug(string sScriptName, string sLineNumber, string sMessage)
{
string sName = GetName(OBJECT_SELF);
if(sName == GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE) &&
sName != "")
{
sMessage = "(((DEBUG)))[" + sScriptName + " - " + sLineNumber + " ]" + sMessage;
sMessage = ai_StripColorCodes(sMessage);
WriteTimestampedLogEntry(sMessage);
return;
}
//sMessage = "(((DEBUG)))[" + sScriptName + " - " + sLineNumber + " ]" + sMessage;
//sMessage = ai_StripColorCodes(sMessage);
//SendMessageToPC(GetFirstPC(), sMessage);
//WriteTimestampedLogEntry(sMessage);
//if(GetLocalInt(OBJECT_SELF, "AI_DEBUG")) WriteTimestampedLogEntry(sMessage);
//if(GetName(OBJECT_SELF) == "Kirrin") WriteTimestampedLogEntry(sMessage);
//if(GetName(OBJECT_SELF) == "Dorna Trapspringer") WriteTimestampedLogEntry(sMessage);
//if(GetName(OBJECT_SELF) == "Dire Spider") WriteTimestampedLogEntry(sMessage);
//if(GetName(OBJECT_SELF) == "Shadow Priest") WriteTimestampedLogEntry(sMessage);
//if(GetName(OBJECT_SELF) == "Tomi Undergallows") WriteTimestampedLogEntry(sMessage);
//if(GetName(OBJECT_SELF) == "Thello Colds") WriteTimestampedLogEntry(sMessage);
//if(GetName(OBJECT_SELF) == "Gert Sigers") WriteTimestampedLogEntry(sMessage);
//if(GetName(OBJECT_SELF) == "Zombie") WriteTimestampedLogEntry(sMessage);
}
void ai_Counter_Start()
{
SetLocalInt(GetModule(), "0_MSCounter", GetMicrosecondCounter());
}
void ai_Counter_End(string sMessage = "")
{
int nTime = GetMicrosecondCounter();
nTime = nTime - GetLocalInt(GetModule(), "0_MSCounter");
float fTime = nTime / 1000000.0;
if(AI_DEBUG) ai_Debug("MICROSECOND_COUNTER", "", "Seconds: " + FloatToString(fTime, 0, 10) +
" Microseconds: " + IntToString(nTime) + " " + sMessage);
}

View File

@ -0,0 +1,544 @@
/*//////////////////////////////////////////////////////////////////////////////
// Script Name: 0i_module
////////////////////////////////////////////////////////////////////////////////
Include script for handling event scripts for injecting the systems into a
module for either single player or a server.
*///////////////////////////////////////////////////////////////////////////////
#include "x2_inc_switches"
#include "0i_associates"
#include "0i_menus"
#include "0i_player_target"
#include "0i_gui_events"
// Add to nw_c2_default9 OnSpawn event script of monsters and
int ai_OnMonsterSpawn(object oCreature);
// Add to nw_ch_ac9 OnSpawn event script of henchman.
void ai_OnAssociateSpawn(object oCreature);
// Run all of the players starting scripts.
// If oPC is passed as Invalid then it will get the firt PC in the game.
void ai_CheckPCStart(object oPC = OBJECT_INVALID);
// Checks to see if we should change the monster via Json.
int ai_ChangeMonster(object oCreature, object oModule);
// Checks to see if we should change the associate via Json.
object ai_ChangeAssociate(object oCreature, object oModule);
// Sets the events for oCreature that is a Monster while playing Infinite Dungeons.
void ai_SetIDMonsterEventScripts(object oCreature);
// Sets the events for oCreature that is a monster in while using the PRC and
// playing Infinite Dungeons.
void ai_SetPRCIDMonsterEventScripts(object oCreature);
// Sets the events for oCreature that is an associate while using the PRC.
void ai_SetPRCAssociateEventScripts(object oCreature);
// Reverts single player monster event scripts back to their default.
void ai_ChangeEventScriptsForMonster(object oCreature);
// Reverts single player associates event scripts back to their default.
void ai_ChangeEventScriptsForAssociate(object oCreature);
// If using PRC this will replace some spells with PRC variants.
json ai_ReplaceSpellsWithPRCVariants(object oCreature, json jCreature);
//******************************************************************************
//********************* Creature event scripts *********************************
//******************************************************************************
int ai_OnMonsterSpawn(object oCreature)
{
if(GetLocalInt(oCreature, AI_ONSPAWN_EVENT)) return FALSE;
SetLocalInt(oCreature, AI_ONSPAWN_EVENT, TRUE);
object oModule = GetModule();
int nInfiniteDungeons;
int nPRC = GetLocalInt(oModule, AI_USING_PRC);
// If you are running a server this will not affect the module.
if(!AI_SERVER)
{
ai_CheckPCStart();
string sModuleName = GetModuleName();
if(sModuleName == "Neverwinter Nights - Infinite Dungeons" ||
sModuleName == "Infinite Dungeons [PRC8]")
{
nInfiniteDungeons = TRUE;
if(nPRC) ai_SetPRCIDMonsterEventScripts(oCreature);
else ai_SetIDMonsterEventScripts(oCreature);
// Fix to get plot givers, finishers from getting killed a lot.
if(GetLocalString(oCreature, "sConversation") == "id1_plotgiver " ||
GetLocalString(oCreature, "sConversation") == "id1_plotdest")
{
ChangeToStandardFaction(oCreature, STANDARD_FACTION_MERCHANT);
SetStandardFactionReputation(STANDARD_FACTION_HOSTILE, 50, oCreature);
}
}
}
// PRC and Infinite dungeons has issues with Ondeath script so we just leave it alone.
if(!nPRC && !nInfiniteDungeons)
{
// We change this script so we can setup permanent summons on/off.
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH);
SetLocalString(oCreature, "AI_ON_DEATH", sScript);
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_c2_7_ondeath");
}
if(GetCreatureFlag(oCreature, CREATURE_VAR_IS_INCORPOREAL))
{
string sCombatAI = GetLocalString(oCreature, AI_DEFAULT_SCRIPT);
if (sCombatAI == "") SetLocalString(oCreature, AI_DEFAULT_SCRIPT, "ai_incorporeal");
}
ai_SetListeningPatterns(oCreature);
ai_SetCreatureAIScript(oCreature);
ai_SetNormalAppearance(oCreature);
ai_SetAura(oCreature);
SetLocalInt(oCreature, AI_HEAL_IN_COMBAT_LIMIT, AI_MONSTER_HEAL_IN_COMBAT_CHANCE);
SetLocalInt(oCreature, AI_HEAL_OUT_OF_COMBAT_LIMIT, AI_MONSTER_HEAL_OUT_COMBAT_CHANCE);
int nMonsterHpIncrease = GetLocalInt(oModule, AI_INCREASE_MONSTERS_HP);
if(nMonsterHpIncrease)
{
int nHp = GetMaxHitPoints(oCreature);
nHp = (nHp * nMonsterHpIncrease) / 100;
effect eHp = EffectTemporaryHitpoints(nHp);
eHp = SupernaturalEffect(eHp);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eHp, oCreature);
}
// Check if the monster should change how they search for targets.
if(d100() <= GetLocalInt(GetModule(), AI_RULE_AI_DIFFICULTY))
{
SetLocalInt(oCreature, AI_RULE_AI_DIFFICULTY, TRUE);
}
// Do json changes after we have setup the creature.
if(ai_ChangeMonster(oCreature, oModule)) return TRUE;
return FALSE;
}
void ai_OnAssociateSpawn(object oCreature)
{
if(GetLocalInt(oCreature, AI_ONSPAWN_EVENT)) return;
SetLocalInt(oCreature, AI_ONSPAWN_EVENT, TRUE);
int bPRC = GetLocalInt(GetModule(), AI_USING_PRC);
// If you are running a server this will not affect the module.
if(!AI_SERVER)
{
if(bPRC) ai_SetPRCAssociateEventScripts(oCreature);
}
// PRC has issues with Ondeath script so we just leave it alone.
if(!bPRC)
{
// We change this script so we can setup permanent summons on/off.
// If you don't use this you may remove the next three lines.
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH);
SetLocalString(oCreature, "AI_ON_DEATH", sScript);
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_ch_7_ondeath");
}
// Initialize Associate modes for basic use.
ai_SetListeningPatterns(oCreature);
ai_SetNormalAppearance(oCreature);
ai_SetAssociateAIScript(oCreature, FALSE);
ai_SetAura(oCreature);
if(GetLocalInt(GetModule(), AI_RULE_PARTY_SCALE)) ai_CheckXPPartyScale(oCreature);
// Bioware summoned shadows are not incorporeal, also set the ai code.
if (GetTag(OBJECT_SELF) == "NW_S_SHADOW")
{
SetLocalInt(OBJECT_SELF, "X2_L_IS_INCORPOREAL", TRUE);
SetLocalString(OBJECT_SELF, AI_DEFAULT_SCRIPT, "ai_shadow");
}
}
void ai_CheckPCStart(object oPC = OBJECT_INVALID)
{
if(oPC == OBJECT_INVALID) oPC = GetFirstPC();
// There should always be a PC widget. If it doesn't exist then we assume
// that the module is being loaded or started.
if(!NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI))
{
object oModule = GetModule();
// Do PRC check and save variable to the module.
if(ResManGetAliasFor("prc_ai_fam_percp", RESTYPE_NCS) != "")
SetLocalInt(oModule, AI_USING_PRC, TRUE);
ai_SetAIRules();
ai_CheckAssociateData(oPC, oPC, "pc");
ai_StartupPlugins(oPC);
ai_SetupPlayerTarget(oPC);
ai_SetupModuleGUIEvents(oPC);
ai_CreateWidgetNUI(oPC, oPC);
ai_SetNormalAppearance(oPC);
}
}
void ai_CopyMonster(object oCreature, object oModule)
{
// After setting the monster lets see if we should copy it.
float fMonsterIncrease = GetLocalFloat(oModule, AI_INCREASE_ENC_MONSTERS);
if(GetIsEncounterCreature(oCreature) && fMonsterIncrease > 0.0)
{
int nMonsterIncrease;
float fMonsterCounter = GetLocalFloat(oModule, "AI_MONSTER_COUNTER");
fMonsterCounter += fMonsterIncrease;
nMonsterIncrease = FloatToInt(fMonsterCounter);
if(nMonsterIncrease > 0)
{
fMonsterCounter = fMonsterCounter - IntToFloat(nMonsterIncrease);
}
SetLocalFloat(oModule, "AI_MONSTER_COUNTER", fMonsterCounter);
while(nMonsterIncrease > 0)
{
CopyObject(oCreature, GetLocation(oCreature), OBJECT_INVALID, "", TRUE);
nMonsterIncrease = nMonsterIncrease - 1;
}
}
}
void ai_CreateMonster(json jCreature, location lLocation, object oModule)
{
//WriteTimestampedLogEntry("0i_module, 181, " + JsonDump(jCreature, 1));
object oCreature = JsonToObject(jCreature, lLocation, OBJECT_INVALID, TRUE);
// Lets set the new version as spawned so we skip the initial setup again.
SetLocalInt(oCreature, AI_ONSPAWN_EVENT, TRUE);
/*if(GetLocalInt(oModule, AI_RULE_CORPSES_STAY))
{
SetIsDestroyable(FALSE, FALSE, TRUE, oCreature);
SetLootable(oCreature, TRUE);
} */
if(AI_DEBUG) ai_Debug("0i_module", "187", GetName(oCreature));
ai_CopyMonster(oCreature, oModule);
return;
}
json ai_SetCompanionSummoning(object oCreature, json jCreature)
{
if(GetHasFeat(FEAT_SUMMON_FAMILIAR, oCreature, TRUE))
{
json jFamiliar = JsonObjectGet(jCreature, "FamiliarName");
jFamiliar = JsonObjectSet(jFamiliar, "value", JsonString("Summoned Familiar"));
jCreature = JsonObjectSet(jCreature, "FamiliarName", jFamiliar);
jFamiliar = JsonObjectGet(jCreature, "FamiliarType");
jFamiliar = JsonObjectSet(jFamiliar, "value", JsonInt(Random(11)));
return JsonObjectSet(jCreature, "FamiliarType", jFamiliar);
}
if(GetHasFeat(FEAT_ANIMAL_COMPANION , oCreature, TRUE))
{
json jCompanion = JsonObjectGet(jCreature, "CompanionName");
jCompanion = JsonObjectSet(jCompanion, "value", JsonString("Summoned Companion"));
jCreature = JsonObjectSet(jCreature, "CompanionName", jCompanion);
jCompanion = JsonObjectGet(jCreature, "CompanionType");
jCompanion = JsonObjectSet(jCompanion, "value", JsonInt(Random(9)));
return JsonObjectSet(jCreature, "CompanionType", jCompanion);
}
return jCreature;
}
int ai_ChangeMonster(object oCreature, object oModule)
{
object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oCreature);
// Lets not mess up the cutscenes with silly RULES.
if(GetCutsceneMode(oPC)) return FALSE;
//float fDistance = GetDistanceBetween(oCreature, oPC);
// Looks bad to see creatures wink in and out plus could cause module errors.
//if(fDistance != 0.0 && fDistance < AI_RANGE_PERCEPTION) return oCreature;
if(IsInConversation(oCreature)) return FALSE;
json jCreature = ObjectToJson(oCreature, TRUE);
// We now use plugins to mod our monsters.
json jMonsterMods = GetLocalJson(oModule, AI_MONSTER_MOD_JSON);
if(JsonGetType(jMonsterMods) != JSON_TYPE_NULL)
{
SetLocalJson(oModule, AI_MONSTER_JSON, jCreature);
SetLocalObject(oModule, AI_MONSTER_OBJECT, oCreature);
int nIndex;
string sMonsterMod = JsonGetString(JsonArrayGet(jMonsterMods, nIndex));
while(sMonsterMod != "")
{
ExecuteScript(sMonsterMod, oPC);
sMonsterMod = JsonGetString(JsonArrayGet(jMonsterMods, ++nIndex));
}
jCreature = GetLocalJson(oModule, AI_MONSTER_JSON);
}
int nSummon = GetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS) &&
(GetHasFeat(FEAT_SUMMON_FAMILIAR, oCreature, TRUE)) ||
GetHasFeat(FEAT_ANIMAL_COMPANION, oCreature, TRUE);
int nPercDist = GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE) != 11 &&
GetReputation(oCreature, oPC) < 11;
//WriteTimestampedLogEntry(GetName(oCreature) + ": fDistance: " + FloatToString(fDistance, 0, 2) + " nSummon: " + IntToString(nSummon) +
// " nPercDist: " + IntToString(nPercDist) + " Reputation: " + IntToString(GetReputation(oCreature, oPC)));
if(nSummon || nPercDist)
{
location lLocation = GetLocation(oCreature);
if(nPercDist)
{
json jPerception = JsonObjectGet(jCreature, "PerceptionRange");
jPerception = JsonObjectSet(jPerception, "value", JsonInt(GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE)));
jCreature = JsonObjectSet(jCreature, "PerceptionRange", jPerception);
}
if(nSummon) jCreature = ai_SetCompanionSummoning(oCreature, jCreature);
SetLocalInt(oModule, AI_MONSTER_CHANGED, TRUE);
}
if(GetLocalInt(oModule, AI_MONSTER_CHANGED))
{
SetIsDestroyable(TRUE, FALSE, FALSE, oCreature);
location lLocation = GetLocation(oCreature);
DestroyObject(oCreature);
AssignCommand(oModule, DelayCommand(1.0, ai_CreateMonster(jCreature, lLocation, oModule)));
DeleteLocalInt(oModule, AI_MONSTER_CHANGED);
return TRUE;
}
else ai_CopyMonster(oCreature, oModule);
DeleteLocalJson(oModule, AI_MONSTER_JSON);
DeleteLocalObject(oModule, AI_MONSTER_OBJECT);
return FALSE;
}
// Special event scripts for Infinite Dungeons!
void ai_SetIDMonsterEventScripts(object oCreature)
{
//if(AI_DEBUG) ai_Debug("0i_module", "433", "Changing " + GetName(oCreature) + "'s Infinte Dungeons event scripts.");
//********** On Heartbeat **********
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT);
SetLocalString(oCreature, "AI_ON_HEARTBEAT", sScript);
if(sScript == "x2_def_heartbeat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else if(sScript == "nw_c2_default1") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_HEARTBEAT SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Perception **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE);
SetLocalString(oCreature, "AI_ON_NOTICE", sScript);
if(sScript == "x2_def_percept") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_id_events");
else if(sScript == "nw_c2_default2") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_NOTICE SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On End Combat Round **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND);
SetLocalString(oCreature, "AI_ON_END_COMBATROUND", sScript);
if(sScript == "x2_def_endcombat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_id_events");
else if(sScript == "nw_c2_default3") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_END_COMBATROUND SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Dialogue **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE);
SetLocalString(oCreature, "AI_ON_DIALOGUE", sScript);
if(sScript == "x2_def_onconv") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_id_events");
else if(sScript == "nw_c2_default4") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_DIALOGUE_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Melee Attacked **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED);
SetLocalString(oCreature, "AI_ON_MELEE_ATTACKED", sScript);
if(sScript == "x2_def_attacked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_id_events");
else if(sScript == "nw_c2_default5") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_MELEE_ATTACKED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Damaged **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED);
SetLocalString(oCreature, "AI_ON_DAMAGED", sScript);
if(sScript == "x2_def_ondamage") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_id_events");
else if(sScript == "nw_c2_default6") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_DAMAGED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
// We don't set OnDeath for Infinite Dungeons!
//********** On Death **********
//sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH);
//SetLocalString(oCreature, "AI_ON_DEATH", sScript);
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_id_events");
//********** On Disturbed **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED);
SetLocalString(oCreature, "AI_ON_DISTURBED", sScript);
if(sScript == "x2_def_ondisturb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_id_events");
else if(sScript == "nw_c2_default8") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_DISTURBED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
//********** On Rested **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED);
SetLocalString(oCreature, "AI_ON_RESTED", sScript);
if(sScript == "x2_def_rested") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_id_events");
else if(sScript == "nw_c2_defaulta") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_RESTED SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Spell Cast At **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT);
SetLocalString(oCreature, "AI_ON_SPELLCASTAT", sScript);
if(sScript == "x2_def_spellcast") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_id_events");
else if(sScript == "nw_c2_defaultb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_SPELLCASTAT_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Blocked **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR);
SetLocalString(oCreature, "AI_ON_BLOCKED_BY_DOOR", sScript);
if(sScript == "x2_def_onblocked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_id_events");
else if(sScript == "nw_c2_defaulte") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_BLOCKED_BY_DOOR SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "");
}
// Special event scripts for Infinite Dungeons with PRC!
void ai_SetPRCIDMonsterEventScripts(object oCreature)
{
//if(AI_DEBUG) ai_Debug("0i_module", "433", "Changing " + GetName(oCreature) + "'s Infinte Dungeons event scripts for PRC.");
//********** On Heartbeat **********
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT);
SetLocalString(oCreature, "AI_ON_HEARTBEAT", sScript);
if(sScript == "x2_def_heartbeat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_prc_id_events");
else if(sScript == "nw_c2_default1") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_HEARTBEAT SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Perception **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE);
SetLocalString(oCreature, "AI_ON_NOTICE", sScript);
if(sScript == "x2_def_percept") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_prc_id_events");
else if(sScript == "nw_c2_default2") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_NOTICE SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On End Combat Round **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND);
SetLocalString(oCreature, "AI_ON_END_COMBATROUND", sScript);
if(sScript == "x2_def_endcombat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_prc_id_events");
else if(sScript == "nw_c2_default3") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_END_COMBATROUND SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Dialogue **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE);
SetLocalString(oCreature, "AI_ON_DIALOGUE", sScript);
if(sScript == "x2_def_onconv") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_prc_id_events");
else if(sScript == "nw_c2_default4") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_DIALOGUE_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Melee Attacked **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED);
SetLocalString(oCreature, "AI_ON_MELEE_ATTACKED", sScript);
if(sScript == "x2_def_attacked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_prc_id_events");
else if(sScript == "nw_c2_default5") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_MELEE_ATTACKED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Damaged **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED);
SetLocalString(oCreature, "AI_ON_DAMAGED", sScript);
if(sScript == "x2_def_ondamage") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_prc_id_events");
else if(sScript == "nw_c2_default6") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_DAMAGED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
// We don't set OnDeath for PRC or Infinite dungeons.
//********** On Death **********
//sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH);
//SetLocalString(oCreature, "AI_ON_DEATH", sScript);
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "0e_prc_id_events");
//********** On Disturbed **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED);
SetLocalString(oCreature, "AI_ON_DISTURBED", sScript);
if(sScript == "x2_def_ondisturb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_prc_id_events");
else if(sScript == "nw_c2_default8") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_DISTURBED_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
//********** On Rested **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED);
SetLocalString(oCreature, "AI_ON_RESTED", sScript);
if(sScript == "x2_def_rested") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_prc_id_events");
else if(sScript == "nw_c2_defaulta") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_RESTED SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Spell Cast At **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT);
SetLocalString(oCreature, "AI_ON_SPELLCASTAT", sScript);
if(sScript == "x2_def_spellcast") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_prc_id_events");
else if(sScript == "nw_c2_defaultb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_SPELLCASTAT_SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//********** On Blocked **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR);
SetLocalString(oCreature, "AI_ON_BLOCKED_BY_DOOR", sScript);
if(sScript == "x2_def_onblocked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_prc_id_events");
else if(sScript == "nw_c2_defaulte") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_prc_id_events");
else if(sScript == "") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_id_events");
else WriteTimestampedLogEntry("ON_BLOCKED_BY_DOOR SCRIPT ERROR: AI did not capture " + sScript + " script for " + GetName(oCreature) + ".");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "");
}
// Special event scripts for PRC associates!
void ai_SetPRCAssociateEventScripts(object oCreature)
{
//if(AI_DEBUG) ai_Debug("0i_module", "433", "Changing " + GetName(oCreature) + "'s Infinte Dungeons event scripts for PRC.");
//********** On Heartbeat **********
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT);
SetLocalString(oCreature, "AI_ON_HEARTBEAT", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_prc_ch_events");
else if(sScript == "nw_ch_ac1") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "0e_prc_ch_events");
//********** On Perception **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE);
SetLocalString(oCreature, "AI_ON_NOTICE", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_prc_ch_events");
else if(sScript == "nw_ch_ac2") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "0e_prc_ch_events");
//********** On End Combat Round **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND);
SetLocalString(oCreature, "AI_ON_END_COMBATROUND", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_prc_ch_events");
else if(sScript == "nw_ch_ac3") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "0e_prc_ch_events");
//********** On Dialogue **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE);
SetLocalString(oCreature, "AI_ON_DIALOGUE", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_prc_ch_events");
else if(sScript == "nw_ch_ac4") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "0e_prc_ch_events");
//********** On Melee Attacked **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED);
SetLocalString(oCreature, "AI_ON_MELEE_ATTACKED", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_prc_ch_events");
else if(sScript == "nw_ch_ac5") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "0e_prc_ch_events");
//********** On Damaged **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED);
SetLocalString(oCreature, "AI_ON_DAMAGED", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_prc_ch_events");
else if(sScript == "nw_ch_ac6") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "0e_prc_ch_events");
//********** On Disturbed **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED);
SetLocalString(oCreature, "AI_ON_DISTURBED", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_prc_ch_events");
else if(sScript == "nw_ch_ac8") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "0e_prc_ch_events");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
//********** On Rested **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED);
SetLocalString(oCreature, "AI_ON_RESTED", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_prc_ch_events");
else if(sScript == "nw_ch_aca") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "0e_prc_ch_events");
//********** On Spell Cast At **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT);
SetLocalString(oCreature, "AI_ON_SPELLCASTAT", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_prc_ch_events");
else if(sScript == "nw_ch_acb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "0e_prc_ch_events");
//********** On Blocked **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR);
SetLocalString(oCreature, "AI_ON_BLOCKED_BY_DOOR", sScript);
if(sScript == "default") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_prc_ch_events");
else if(sScript == "nw_ch_ace") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "0e_prc_ch_events");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "");
if(!GetCommandable(oCreature)) SetCommandable(TRUE, oCreature);
}
void ai_ChangeEventScriptsForMonster(object oCreature)
{
//********** On Heartbeat **********
string sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT);
if(sScript == "0e_c2_1_hb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "nw_c2_default1");
//********** On Perception **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE);
if(sScript == "0e_c2_2_percept") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "nw_c2_default2");
//********** On End Combat Round **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND);
if(sScript == "0e_c2_3_endround") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "nw_c2_default3");
//********** On Dialogue **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE);
if(sScript == "0e_c2_4_convers") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "nw_c2_default4");
//********** On Melee Attacked **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED);
if(sScript == "0e_c2_5_phyatked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "nw_c2_default5");
//********** On Damaged **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED);
if(sScript == "0e_c2_6_damaged") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "nw_c2_default6");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "nw_c2_deafult7");
//********** On Disturbed **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED);
if(sScript == "0e_c2_8_disturb") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "nw_c2_default8");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "nw_c2_defaulta");
//********** On Spell Cast At **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT);
if(sScript == "0e_c2_b_castat") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "nw_c2_defaultb");
//********** On Blocked **********
sScript = GetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR);
if(sScript == "0e_c2_e_blocked") SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "nw_c2_defaulte");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "nw_c2_defaulte");
}
void ai_ChangeEventScriptsForAssociate(object oCreature)
{
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "nw_ch_ac1");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_NOTICE, "nw_ch_ac2");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "nw_ch_ac3");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "nw_ch_ac4");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "nw_ch_ac5");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "nw_ch_ac6");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DEATH, "nw_ch_ac7");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "nw_ch_ac8");
//SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_RESTED, "nw_ch_aca");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "nw_ch_acb");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "nw_ch_ace");
SetEventScript(oCreature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "nw_ch_acd");
}

434
src/module/nss/0i_nui.nss Normal file
View File

@ -0,0 +1,434 @@
/*//////////////////////////////////////////////////////////////////////////////
// Script Name: 0i_nui
////////////////////////////////////////////////////////////////////////////////
Include script for handling window displays.
Use the following to get/set window information.
string sBind = NuiGetNthBind (oPlayer, nToken, FALSE, #);
json jMenuInfo = NuiGetBind (oPlayer, nToken, sBind);
# Gets json information for window :
0 - string - "window_title"
1 - json - "window_geometry" : "h", "w", "x", "y"
2 - bool - "window_resizable"
3 - bool - "window_closable"
4 - bool - "window_transparent"
5 - bool - "window_border"
Layout pixel sizes:
Pixel height Title bar 33.
Pixel height Top border 10, between widgets 8, bottom border 10.
Pixel width Left border 10, between widgets 4, right border 10.
Group outer lines add 12 to the vertical and horizontal lines.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_main"
#include "nw_inc_nui"
struct stComboBox
{
json jIndex;
json jCombo;
json jRow;
json jResRefArray;
json jWinArray;
json jCanSummon; // Index of all the summons in summons.2da
};
// Saves the menu to the campaign database.
void SaveMenuToCampaignDb(object oPC, int nToken, string sWndId);
// Returns the middle of the screen for the x position.
// oPC using the menu.
// fMenuWidth - the width of the menu to display.
float GetGUIWidthMiddle(object oPC, float fMenuWidth);
// Returns the middle of the screen for the y position.
// oPC using the menu.
// fMenuHeight - the height of the menu to display.
float GetGUIHeightMiddle(object oPC, float fMenuHeight);
// Checks to see if sWndId is open.
// If the window is open it removes it and returns FALSE
// If the window is closed it returns TRUE
int IsWindowClosed(object oPC, string sWndId);
// Returns the Window ID (nToken).
// oPC is the PC using the menu.
// jLayout is the Layout of the menu.
// sWinID is the string ID for this window.
// sTitle is the Title of the menu.
// fX is the X position of the menu (-1.0: Centers, -2.0: UpperRight on Mouse, -3.0: Centers top of mouse).
// fY is the Y position of the menu (-1.0: Centers, -2.0: UpperRight on Mouse, -3.0: Centers top of mouse).
// fWidth is the width of the menu.
// fHeight is the height of the menu.
// bResize - TRUE will all it to be resized.
// bCollapse - TRUE will allow the window to be collapsable.
// bClose - TRUE will allow the window to be closed.
// bTransparent - TRUE makes the menu transparent.
// bBorder - TRUE makes the menu have a border.
// sEventScript will fire this event script for this window.
int SetWindow(object oPC, json jLayout, string sWinID, string sTitle, float fX, float fY, float fWidth, float fHeight, int bResize, int bCollapse, int bClose, int bTransparent, int bBorder, string sEventScript = "");
// Creates a label element in jRow.
// jRow is the row the label goes into.
// sLabel is the text placed in the label.
// If "" is passed then it will create a bind of sId + "_label".
// fWidth is the width of the label.
// fHeight is the Height of the label.
// nHAlign is horizonal align [NUI_HALING_*].
// nVAlign is vertial align [NUI_VALING_*].
// sId is the bind the event uses sId + "_event".
// sTooltip is the tooltip bind value.
json CreateLabel(json jRow, string sLabel, string sId, float fWidth, float fHeight, int nHAlign = 0, int nVAlign = 0, float fMargin = -1.0, string sTooltip = "");
// Creates a basic button element in jRow.
// jRow is the row the label goes into.
// sLabel is the text placed in the button. If "" is passed then it will
// create a bind of sId + "_label".
// sId is the binds for the button and the event uses sId + "_event".
// fWidth is the width of the button.
// fHeight is the Height of the button.
// fMargin is the space around the button.
// sTooltip is the tooltip bind value.
json CreateButton(json jRow, string sLabel, string sId, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = "");
// Creates a basic button select element in jRow.
// jRow is the row the label goes into.
// sLabel is the text placed in the button. If "" is passed then it will
// create a bind of sId + "_label".
// sId is the binds for the button and the event uses sId + "_event".
// fWidth is the width of the button.
// fHeight is the Height of the button.
// sTooltip is the tooltip bind value.
json CreateButtonSelect(json jRow, string sLabel, string sId, float fWidth, float fHeight, string sToolTip = "");
// Creates a button element with an image in jRow.
// jRow is the row the label goes into.
// sImage is the resref of the image to use.
// If "" is passed then it will create a bind of sId + "_image".
// sId is the binds for the button and the event uses sId + "_event".
// fWidth is the width of the button.
// fHeight is the Height of the button.
// fMargin is the space around the button.
// sTooltip is the tooltip bind value.
json CreateButtonImage(json jRow, string sResRef, string sId, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = "");
// Creates a basic text box that is not editable element in jRow.
// jRow is the row the TextEdit box goes into.
// sId is the bind variable so we can change the text.
// fWidth the width of the box.
// fHeight the height of the box.
// bBorder will add border TRUE or remove it FALSE.
// nScroll use NUI_SCROLLBARS_*
// sTooltip is the tooltip bind value.
json CreateTextBox(json jRow, string sId, float fWidth, float fHeight, int bBorder = TRUE, int nScroll = NUI_SCROLLBARS_AUTO, string sTooltip = "");
// Creates a basic text edit box element in jRow.
// jRow is the row the TextEdit box goes into.
// sPlaceHolderBind is the bind for Placeholder.
// sValueBind is the bind variable so we can change the text.
// nMaxLength is the maximum lenght of the text (1 - 65535)
// bMultiline - True or False that is has multiple lines.
// fWidth the width of the box.
// fHeight the height of the box.
// sTooltip is the tooltip bind value.
json CreateTextEditBox(json jRow, string sPlaceHolderBind, string sValueBind, int nMaxLength, int bMultiline, float fWidth, float fHeight, string sToolTip = "");
// Creates a combo box element in jRow.
// jRow is the row the combo goes into.
// jCombo is the elements/list for the combo box. Use NuiComboEntry to add.
// sId is the binds for the combo and the event uses sId + "_event"
// sId + "_selected" is the bind for the selection in the combo box.
// fWidth is the width of the combo.
// fHeight is the Height of the combo.
// sTooltip is the tooltip bind value.
json CreateCombo(json jRow, json jCombo, string sId, float fWidth, float fHeight, string sToolTip = "");
// Creates an image element in jRow.
// jRow is the row the Image goes into.
// sImage is the resref of the image to use. If "" is passed then it will
// create a bind of sId + "_image".
// nAspect is the aspect of the image NUI_ASPECT_*.
// nHAlign is the horizontal alignment of the image NUI_HALIGN_*.
// nVAlign is the vertical alignment of the image NUI_VALIGN_*.
// fWidth the width of the box.
// fHeight the height of the box.
// sTooltip is the tooltip bind value.
json CreateImage(json jRow, string sResRef, string sId, int nAspect, int nHAlign, int nVAlign, float fWidth, float fHeight, float fMargin = -1.0, string sToolTip = "");
// Creates a check box element in jRow.
// jRow is the row the Checkbox box goes into.
// sLabel is the text placed in the label.
// If "" is passed then it will create a bind of sId + "_label".
// sId is the bind variable so we can change the text.
// sId + "_check" is the Bind:bool for if it is checked or not.
// fWidth is the width of the label.
// fHeight is the Height of the label.
// sTooltip is the tooltip bind value.
json CreateCheckBox(json jRow, string sLabel, string sId, float fWidth, float fHeight, string sToolTip = "");
// Creates a slider (Int based) element in jRow
// jRow is the row the Check box goes into.
// sId is the bind name.
// The binds are as follows.
// Value: sId + "_value"
// Minimum: sId + "_min"
// Maximum: sId + "_max"
// Step size: sId + "_stepsize"
// fWidth is the width of the slider.
// fHeight is the Height of the slider.
// sTooltip is the tooltip bind value.
json CreateSlider(json jRow, string sId, float fWidth, float fHeight, string sToolTip = "");
// Creates an Options element in jRow.
// jRow is the row the Options will start on.
// sId is the bind name.
// The binds are as follows:
// Value: sId + "_value"
// Event is sId + "_event"
// nDirection: NUI_DIRECTION_*
// fWidth is the width of the options labels.
// fHeight is the height of the options labels.
// sTooltip is the tooltip bind value.
json CreateOptions(json jRow, string sId, int nDirection, json jLabels, float fWidth, float fHeight, string sToolTip = "");
// Creates a list element in jRow.
// jRow is the row the list will start on.
// jElements is the list of elements in the list. Use NuiListTemplateCell to add.
// sId is the bind name.
// The binds are Event is sId + "_event".
// Row count is bound to sId + "_count".
// fRowHeight is the height of the rendered rows.
// fWidth is the width of the options labels.
// fHeight is the height of the options labels.
// sTooltip is the tooltip bind value.
json CreateList(json jRow, json jElements, string sId, float fRowHeight, float fWidth, float fHeight, string sTooltip = "");
// Placed here temporarily until we can clean up our includes!
void ai_SetDMWAccessButton(int nButton, int bOn = TRUE);
int ai_GetDMWAccessButton(int nButton);
void ai_SetDMAIAccessButton(int nButton, int bOn = TRUE);
int ai_GetDMAIAccessButton(int nButton);
void SaveMenuToCampaignDb(object oPC, int nToken, string sWndId)
{
json jGeometry = NuiGetBind(oPC, nToken, "window_geometry");
float fX = JsonGetFloat(JsonObjectGet(jGeometry, "x"));
float fY = JsonGetFloat(JsonObjectGet(jGeometry, "y"));
string sName = ai_RemoveIllegalCharacters(GetName(oPC));
json jLocations = ai_GetCampaignDbJson("locations", sName, AI_DM_TABLE);
json jNUI = JsonObjectGet(jLocations, sWndId);
if(JsonGetType(jNUI) == JSON_TYPE_NULL) jNUI = JsonObject();
jNUI = JsonObjectSet(jNUI, "x", JsonFloat(fX));
jNUI = JsonObjectSet(jNUI, "y", JsonFloat(fY));
jLocations = JsonObjectSet(jLocations, sWndId, jNUI);
ai_SetCampaignDbJson("locations", jLocations, sName, AI_DM_TABLE);
}
float GetGUIWidthMiddle(object oPC, float fMenuWidth)
{
// Get players window information.
float fGUI_Width = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_WIDTH));
float fGUI_Scale = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0;
fMenuWidth = fMenuWidth * fGUI_Scale;
return (fGUI_Width / 2.0) - (fMenuWidth / 2.0);
}
float GetGUIHeightMiddle(object oPC, float fMenuHeight)
{
// Get players window information.
float fGUI_Height = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_HEIGHT));
float fGUI_Scale = IntToFloat(GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0;
fMenuHeight = fMenuHeight * fGUI_Scale;
return (fGUI_Height / 2.0) - (fMenuHeight / 2.0);
}
int IsWindowClosed(object oPC, string sWndId)
{
int nToken = NuiFindWindow(oPC, sWndId);
if(nToken)
{
NuiDestroy(oPC, nToken);
return FALSE;
}
return TRUE;
}
int SetWindow(object oPC, json jLayout, string sWinID, string sTitle, float fX, float fY, float fWidth, float fHeight, int bResize, int bCollapse, int bClose, int bTransparent, int bBorder, string sEventScript = "")
{
json jWindow;
if (bCollapse) jWindow = NuiWindow (jLayout, NuiBind ("window_title"), NuiBind ("window_geometry"),
NuiBind ("window_resizable"), JsonNull (), NuiBind ("window_closable"),
NuiBind ("window_transparent"), NuiBind ("window_border"));
else jWindow = NuiWindow (jLayout, NuiBind ("window_title"), NuiBind ("window_geometry"),
NuiBind ("window_resizable"), JsonBool (FALSE), NuiBind ("window_closable"),
NuiBind ("window_transparent"), NuiBind ("window_border"));
int nToken = NuiCreate (oPC, jWindow, sWinID, sEventScript);
if(!bCollapse && !bClose && !bBorder) NuiSetBind (oPC, nToken, "window_title", JsonBool (FALSE));
else NuiSetBind (oPC, nToken, "window_title", JsonString (sTitle));
if (fX == -1.0) fX = GetGUIWidthMiddle (oPC, fWidth);
if (fY == -1.0) fY = GetGUIHeightMiddle (oPC, fHeight);
int nScale = GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE);
if(nScale != 100)
{
fHeight = fHeight * (IntToFloat(1050 - nScale) / 1000.0);
fWidth = fWidth * (IntToFloat(1200 - nScale) / 1000.0);
}
NuiSetBind (oPC, nToken, "window_geometry", NuiRect (fX,
fY, fWidth, fHeight));
NuiSetBind (oPC, nToken, "window_resizable", JsonBool (bResize));
NuiSetBind (oPC, nToken, "window_closable", JsonBool (bClose));
NuiSetBind (oPC, nToken, "window_transparent", JsonBool (bTransparent));
NuiSetBind (oPC, nToken, "window_border", JsonBool (bBorder));
return nToken;
}
json CreateLabel(json jRow, string sLabel, string sId, float fWidth, float fHeight, int nHAlign = 0, int nVAlign = 0, float fMargin = -1.0, string sTooltip = "")
{
json jLabel;
if(sLabel == "") jLabel = NuiId(NuiLabel(NuiBind(sId + "_label"), JsonInt(nHAlign), JsonInt(nVAlign)), sId);
else jLabel = NuiId(NuiLabel(JsonString(sLabel), JsonInt(nHAlign), JsonInt(nVAlign)), sId);
jLabel = NuiWidth(jLabel, fWidth);
jLabel = NuiHeight(jLabel, fHeight);
if (fMargin > -1.0) jLabel = NuiMargin(jLabel, fMargin);
if(sTooltip != "") jLabel = NuiTooltip (jLabel, NuiBind (sTooltip));
return JsonArrayInsert(jRow, jLabel);
}
json CreateButton(json jRow, string sLabel, string sId, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = "")
{
json jButton;
if(sLabel == "") jButton = NuiEnabled(NuiId(NuiButton(NuiBind (sId + "_label")), sId), NuiBind(sId + "_event"));
else jButton = NuiEnabled(NuiId(NuiButton(JsonString(sLabel)), sId), NuiBind(sId + "_event"));
jButton = NuiWidth(jButton, fWidth);
jButton = NuiHeight(jButton, fHeight);
if (fMargin > -1.0) jButton = NuiMargin(jButton, fMargin);
if (sTooltip != "") jButton = NuiTooltip(jButton, NuiBind (sTooltip));
return JsonArrayInsert(jRow, jButton);
}
json CreateButtonSelect(json jRow, string sLabel, string sId, float fWidth, float fHeight, string sTooltip = "")
{
json jButton;
if(sLabel == "") jButton = NuiEnabled(NuiId(NuiButtonSelect(NuiBind (sId + "_label"), NuiBind(sId)), sId), NuiBind(sId + "_event"));
else jButton = NuiEnabled(NuiId(NuiButtonSelect(JsonString(sLabel), NuiBind(sId)), sId), NuiBind(sId + "_event"));
jButton = NuiWidth(jButton, fWidth);
jButton = NuiHeight(jButton, fHeight);
if(sTooltip != "") jButton = NuiTooltip(jButton, NuiBind (sTooltip));
return JsonArrayInsert(jRow, jButton);
}
json CreateButtonImage(json jRow, string sResRef, string sId, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = "")
{
json jButton;
if(sResRef == "") jButton = NuiEnabled(NuiId (NuiButtonImage(NuiBind(sId + "_image")), sId), NuiBind(sId + "_event"));
else jButton = NuiEnabled(NuiId(NuiButtonImage(JsonString(sResRef)), sId), NuiBind(sId + "_event"));
jButton = NuiWidth(jButton, fWidth);
jButton = NuiHeight(jButton, fHeight);
if(fMargin > -1.0) jButton = NuiMargin(jButton, fMargin);
if(sTooltip != "") jButton = NuiTooltip(jButton, NuiBind (sTooltip));
jButton = NuiEncouraged(jButton, NuiBind(sId + "_encouraged"));
return JsonArrayInsert(jRow, jButton);
}
json CreateTextBox(json jRow, string sId, float fWidth, float fHeight, int bBorder = TRUE, int nScroll = NUI_SCROLLBARS_AUTO, string sTooltip = "")
{
json jTextBox = NuiEnabled(NuiText(NuiBind(sId), bBorder, nScroll), NuiBind(sId + "_event"));
jTextBox = NuiWidth(jTextBox, fWidth);
jTextBox = NuiHeight(jTextBox, fHeight);
if(sTooltip != "") jTextBox = NuiTooltip(jTextBox, NuiBind (sTooltip));
return JsonArrayInsert(jRow, JsonObjectSet(jTextBox, "text_color", NuiColor (255, 0, 0)));
}
json CreateTextEditBox(json jRow, string sPlaceHolderBind, string sValueBind, int nMaxLength, int bMultiline, float fWidth, float fHeight, string sTooltip = "")
{
json jObject = NuiEnabled(NuiTextEdit(NuiBind(sPlaceHolderBind), NuiBind(sValueBind), nMaxLength, bMultiline), NuiBind(sValueBind + "_event"));
jObject = NuiWidth(jObject, fWidth);
jObject = NuiHeight(jObject, fHeight);
if(sTooltip != "") jObject = NuiTooltip(jObject, NuiBind (sTooltip));
return JsonArrayInsert(jRow, jObject);
}
json CreateCombo(json jRow, json jList, string sId, float fWidth, float fHeight, string sTooltip = "")
{
json jCombo;
if(JsonGetType(jList) == JSON_TYPE_NULL)
{
jCombo = NuiId(NuiCombo(NuiBind(sId + "_list"), NuiBind(sId + "_selected")), sId + "_event");
}
jCombo = NuiId(NuiCombo(jList, NuiBind (sId + "_selected")), sId);
jCombo = NuiEnabled(jCombo, NuiBind (sId + "_event"));
jCombo = NuiWidth(jCombo, fWidth);
jCombo = NuiHeight(jCombo, fHeight);
if(sTooltip != "") jCombo = NuiTooltip(jCombo, NuiBind(sTooltip));
return JsonArrayInsert(jRow, jCombo);
}
json CreateImage(json jRow, string sResRef, string sId, int nAspect, int nHAlign, int nVAlign, float fWidth, float fHeight, float fMargin = -1.0, string sTooltip = "")
{
json jImage;
if(sResRef == "") jImage = NuiEnabled(NuiId(NuiImage(NuiBind(sId + "_image"), JsonInt(nAspect), JsonInt(nHAlign), JsonInt(nVAlign)), sId), NuiBind(sId + "_event"));
else jImage = NuiEnabled(NuiId(NuiImage(JsonString(sResRef), JsonInt(nAspect), JsonInt(nHAlign), JsonInt(nVAlign)), sId), NuiBind(sId + "_event"));
jImage = NuiWidth(jImage, fWidth);
jImage = NuiHeight(jImage, fHeight);
if (fMargin > -1.0) jImage = NuiMargin(jImage, fMargin);
if(sTooltip != "") jImage = NuiTooltip(jImage, NuiBind(sTooltip));
return JsonArrayInsert(jRow, jImage);
}
json CreateCheckBox(json jRow, string sLabel, string sId, float fWidth, float fHeight, string sTooltip = "")
{
json jCheckBox;
if(sLabel == "") jCheckBox = NuiEnabled(NuiId(NuiCheck(NuiBind(sId + "_label"), NuiBind(sId + "_check")), sId), NuiBind(sId + "_event"));
else jCheckBox = NuiEnabled(NuiId(NuiCheck(JsonString(sLabel), NuiBind(sId + "_check")), sId), NuiBind(sId + "_event"));
jCheckBox = NuiWidth(jCheckBox, fWidth);
jCheckBox = NuiHeight(jCheckBox, fHeight);
if (sTooltip != "") jCheckBox = NuiTooltip (jCheckBox, NuiBind (sTooltip));
return JsonArrayInsert(jRow, jCheckBox);
}
json CreateSlider(json jRow, string sId, float fWidth, float fHeight, string sTooltip = "")
{
json jSlider;
jSlider = NuiEnabled(NuiId(NuiSlider(NuiBind(sId + "_value"), NuiBind(sId + "_min"), NuiBind(sId + "_max"), NuiBind(sId + "_stepsize")), sId), NuiBind(sId + "_event"));
jSlider = NuiWidth(jSlider, fWidth);
jSlider = NuiHeight(jSlider, fHeight);
if(sTooltip != "") jSlider = NuiTooltip(jSlider, NuiBind(sTooltip));
return JsonArrayInsert(jRow, jSlider);
}
json CreateOptions(json jRow, string sId, int nDirection, json jLabels, float fWidth, float fHeight, string sTooltip = "")
{
json jOption;
jOption = NuiEnabled(NuiId(NuiOptions(nDirection, jLabels, NuiBind(sId + "_value")), sId), NuiBind(sId + "_event"));
jOption = NuiWidth(jOption, fWidth);
jOption = NuiHeight(jOption, fHeight);
if(sTooltip != "") jOption = NuiTooltip (jOption, NuiBind (sTooltip));
return JsonArrayInsert(jRow, jOption);
}
json CreateList(json jRow, json jElements, string sId, float fRowHeight, float fWidth, float fHeight, string sTooltip = "")
{
json jList;
jList = NuiId(NuiList(jElements, NuiBind(sId), fRowHeight), sId + "_id");
jList = NuiWidth(jList, fWidth);
jList = NuiHeight(jList, fHeight);
if (sTooltip != "") jList = NuiTooltip(jList, NuiBind(sTooltip));
return JsonArrayInsert(jRow, jList);
}
void ai_SetDMWAccessButton(int nButton, int bOn = TRUE)
{
json jRules = ai_GetCampaignDbJson("rules");
int nWidgetButtons = JsonGetInt(JsonObjectGet(jRules, sDMWidgetAccessVarname));
if(bOn) nWidgetButtons = nWidgetButtons | nButton;
else nWidgetButtons = nWidgetButtons & ~nButton;
SetLocalInt(GetModule(), sDMWidgetAccessVarname, nWidgetButtons);
jRules = JsonObjectSet(jRules, sDMWidgetAccessVarname, JsonInt(nWidgetButtons));
ai_SetCampaignDbJson("rules", jRules);
}
int ai_GetDMWAccessButton(int nButton)
{
int nWidgetButtons = GetLocalInt(GetModule(), sDMWidgetAccessVarname);
return nWidgetButtons & nButton;
}
void ai_SetDMAIAccessButton(int nButton, int bOn = TRUE)
{
json jRules = ai_GetCampaignDbJson("rules");
int nWidgetButtons = JsonGetInt(JsonObjectGet(jRules, sDMAIAccessVarname));
if(bOn) nWidgetButtons = nWidgetButtons | nButton;
else nWidgetButtons = nWidgetButtons & ~nButton;
SetLocalInt(GetModule(), sDMAIAccessVarname, nWidgetButtons);
jRules = JsonObjectSet(jRules, sDMAIAccessVarname, JsonInt(nWidgetButtons));
ai_SetCampaignDbJson("rules", jRules);
}
int ai_GetDMAIAccessButton(int nButton)
{
int nWidgetButtons = GetLocalInt(GetModule(), sDMAIAccessVarname);
return nWidgetButtons & nButton;
}

View File

@ -0,0 +1,793 @@
/*//////////////////////////////////////////////////////////////////////////////
// Script Name: 0i_player_target
////////////////////////////////////////////////////////////////////////////////
Include script for handling player targeting functions.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
#include "0i_menus"
// Setup an AI OnPlayerTarget Event script while allowing any module onplayer
// target event script to still work.
void ai_SetupPlayerTarget(object oCreature);
// Selects a target for oAssocite to follow.
void ai_AllSelectTarget(object oPC, object oAssociate, object oTarget);
// Removes the Cutscene ghosts and variables from all associates. For original AI scripts.
void ai_OriginalRemoveAllActionMode(object oPC);
// Removes the Cutscene ghosts and Command mode from all associates.
void ai_RemoveAllActionMode(object oPC);
// Once a trap has been selected from the associates inventory move to placing the trap.
void ai_SelectTrap(object oPC, object oAssociate, object oItem);
// Place the selected trap at the location selected by the player for OBJECT_SELF.
void ai_PlaceTrap(object oPC, location lLocation);
// Adds a creature to nGroup for oDM
void ai_AddToGroup(object oDM, object oTarget, string sTargetMode);
// Has nGroup perform an action based on the selected target or location.
void ai_DMAction(object oDM, object oTarget, location lLocation, string sTargetMode);
// Get oPC to select a spell target for oAssociate.
void ai_SelectWidgetSpellTarget(object oPC, object oAssociate, string sElem);
// Updates oAssociates widget by destroying the current one and rebuilding.
void ai_UpdateAssociateWidget(object oPC, object oAssociate);
// Sets oAssociates action mode for nFeat from the quick widget menu
int ai_SetActionMode(object oAssociate, int nFeat);
void ai_SetupPlayerTarget(object oCreature)
{
object oModule = GetModule();
string sModuleTargetEvent = GetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_TARGET);
if(sModuleTargetEvent != "")
{
if(sModuleTargetEvent != "0e_player_target") SetLocalString(oModule, AI_MODULE_TARGET_EVENT, sModuleTargetEvent);
}
SetEventScript(oModule, EVENT_SCRIPT_MODULE_ON_PLAYER_TARGET, "0e_player_target");
}
void ai_OriginalActionAssociate(object oPC, object oTarget, location lLocation)
{
object oAssociate = OBJECT_SELF;
if(!GetLocalInt(oAssociate, sGhostModeVarname) && GetLocalInt(oPC, sGhostModeVarname))
{
effect eGhost = EffectCutsceneGhost();
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oAssociate);
SetLocalInt(oAssociate, sGhostModeVarname, TRUE);
}
int nObjectType = GetObjectType(oTarget);
ai_ClearCreatureActions(TRUE);
if(oTarget == GetArea(oPC))
{
ActionMoveToLocation(lLocation, TRUE);
if(GetLocalObject(oPC, AI_FOLLOW_TARGET) == oAssociate)
{
float fFollowDistance = 3.0;
AssignCommand(oPC, ai_ClearCreatureActions());
AssignCommand(oPC, ActionForceFollowObject(oAssociate, fFollowDistance));
}
}
else if(nObjectType == OBJECT_TYPE_CREATURE)
{
if(oTarget != GetLocalObject(oPC, AI_TARGET_ASSOCIATE))
{
if(GetMaster(oTarget) == oPC)
{
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION");
SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oTarget);
ai_SendMessages(GetName(oTarget) + " is now in Action Mode.", AI_COLOR_YELLOW, oPC);
}
else ActionMoveToObject(oTarget, TRUE);
}
}
else if(nObjectType == OBJECT_TYPE_DOOR)
{
if(GetIsTrapped(oTarget) && GetAssociateState(NW_ASC_DISARM_TRAPS, oAssociate))
{
if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate);
if(GetTrapDetectedBy(oTarget, oAssociate))
{
bkAttemptToDisarmTrap(oTarget);
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
}
if(GetLocked(oTarget)) bkAttemptToOpenLock(oTarget);
if(GetIsOpen(oTarget))
{
ActionCloseDoor(oTarget, TRUE);
}
else ActionOpenDoor(oTarget, TRUE);
}
else if(nObjectType == OBJECT_TYPE_ITEM)
{
ActionPickUpItem(oTarget);
}
else if(nObjectType == OBJECT_TYPE_PLACEABLE)
{
ActionMoveToObject(oTarget, TRUE);
if(GetHasInventory(oTarget))
{
if(GetIsTrapped(oTarget) && GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oAssociate))
{
if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate);
if(GetTrapDetectedBy(oTarget, oAssociate))
{
bkAttemptToDisarmTrap(oTarget);
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
if(GetLocked(oTarget))
{
if(GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oAssociate))
{
bkAttemptToOpenLock(oTarget);
}
else AssignCommand(oAssociate, ai_HaveCreatureSpeak(oAssociate, 0, "This " + GetName(oTarget) + " is locked!"));
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE);
}
else if(GetLocked(oTarget))
{
if(GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oAssociate))
{
bkAttemptToOpenLock(oTarget);
}
else AssignCommand(oAssociate, ai_HaveCreatureSpeak(oAssociate, 0, "This " + GetName(oTarget) + " is locked!"));
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE);
}
DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE);
}
else if(nObjectType == OBJECT_TYPE_TRIGGER)
{
if(GetIsTrapped(oTarget) && GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS, oAssociate))
{
if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate);
if(GetTrapDetectedBy(oTarget, oAssociate)) bkAttemptToDisarmTrap(oTarget);
}
}
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
}
void ai_OriginalActionAllAssociates(object oPC, object oTarget, location lLocation)
{
object oAssociate;
int nIndex;
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
{
oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_OriginalActionAssociate(oPC, oTarget, lLocation));
}
for(nIndex = 2; nIndex < 6; nIndex++)
{
oAssociate = GetAssociate(nIndex, oPC);
if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_OriginalActionAssociate(oPC, oTarget, lLocation));
}
}
void ai_ActionAssociate(object oPC, object oTarget, location lLocation)
{
object oAssociate = OBJECT_SELF;
if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) &&
!ai_GetAIMode(oAssociate, AI_MODE_GHOST) &&
!GetLocalInt(oAssociate, sGhostModeVarname))
{
effect eGhost = EffectCutsceneGhost();
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oAssociate);
SetLocalInt(oAssociate, sGhostModeVarname, TRUE);
}
int nObjectType = GetObjectType(oTarget);
ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, TRUE);
ai_ClearCreatureActions(TRUE);
if(oTarget == GetArea(oPC))
{
ActionMoveToLocation(lLocation, TRUE);
if(GetLocalObject(oPC, AI_FOLLOW_TARGET) == oAssociate)
{
float fFollowDistance = ai_GetFollowDistance(oPC);
if(GetDistanceBetween(oAssociate, oPC) <= fFollowDistance)
{
DelayCommand(fFollowDistance, AssignCommand(oPC, ActionMoveToObject(oAssociate, TRUE, fFollowDistance)));
}
else AssignCommand(oPC, ActionMoveToObject(oAssociate, TRUE, fFollowDistance));
}
}
else if(nObjectType == OBJECT_TYPE_CREATURE)
{
if(GetIsDead(oTarget))
{
AssignCommand(oAssociate, ActionDoCommand(ai_SearchObject(oAssociate, oTarget, oPC, TRUE)));
}
else if(GetIsEnemy(oTarget, oAssociate))
{
// Lock them into attacking this target only.
SetLocalObject(oAssociate, AI_PC_LOCKED_TARGET, oTarget);
// This resets a henchmens failed Moral save in combat.
if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_coward")
{
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, GetLocalString(oAssociate, AI_DEFAULT_SCRIPT));
}
if(ai_GetIsInCombat(oAssociate)) ai_DoAssociateCombatRound(oAssociate, oTarget);
else
{
ai_HaveCreatureSpeak(oAssociate, 5, ":0:1:2:3:6:");
ai_StartAssociateCombat(oAssociate, oTarget);
}
ai_SendMessages(GetName(oAssociate) + " is attacking " + GetName(oTarget), AI_COLOR_RED, oPC);
}
else
{
ActionMoveToObject(oTarget, TRUE);
// Player will be stuck with this variable if they are not using the AI.
DeleteLocalInt(oTarget, "AI_I_AM_BEING_HEALED");
ActionDoCommand(ai_ActionTryHealing(oAssociate, oTarget));
}
}
else if(nObjectType == OBJECT_TYPE_DOOR)
{
if(GetIsTrapped(oTarget))
{
if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate);
if(GetTrapDetectedBy(oTarget, oAssociate))
{
int bStopAction = !GetLocalInt(oTarget, "AI_CANNOT_TRAP_" + GetTag(oAssociate));
if(ai_ReactToTrap(oAssociate, oTarget, TRUE)) bStopAction = TRUE;
if(bStopAction)
{
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
}
}
if(GetLocked(oTarget)) ai_AttemptToByPassLock(oAssociate, oTarget, TRUE);
else if(GetIsOpen(oTarget)) ActionCloseDoor(oTarget, TRUE);
else ActionOpenDoor(oTarget, TRUE);
}
else if(nObjectType == OBJECT_TYPE_ITEM)
{
ActionPickUpItem(oTarget);
}
else if(nObjectType == OBJECT_TYPE_PLACEABLE)
{
ActionMoveToObject(oTarget, TRUE);
if(GetHasInventory(oTarget))
{
if(GetIsTrapped(oTarget))
{
if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate);
if(GetTrapDetectedBy(oTarget, oAssociate))
{
if(ai_ReactToTrap(oAssociate, oTarget, TRUE))
{
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
}
}
if(GetLocked(oTarget)) ai_AttemptToByPassLock(oAssociate, oTarget, TRUE);
else ActionDoCommand(ai_SearchObject(oAssociate, oTarget, oPC, TRUE));
}
else
{
if(ai_GetAIMode(oAssociate, AI_MODE_BASH_LOCKS))
{
AssignCommand(oAssociate, ai_ClearCreatureActions());
// Check to make sure we are using a melee weapon.
if(ai_GetIsMeleeWeapon(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oAssociate)) ||
ai_EquipBestMeleeWeapon(oAssociate))
{
AssignCommand(oAssociate, ActionWait(1.0));
AssignCommand(oAssociate, ActionAttack(oTarget));
}
}
else AssignCommand(oAssociate, DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE));
}
}
else if(nObjectType == OBJECT_TYPE_TRIGGER)
{
if(GetIsTrapped(oTarget))
{
if(GetTrapDetectedBy(oTarget, oPC)) SetTrapDetectedBy(oTarget, oAssociate);
if(GetTrapDetectedBy(oTarget, oAssociate)) ai_ReactToTrap(oAssociate, oTarget, TRUE);
}
}
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
}
void ai_ActionAllAssociates(object oPC, object oTarget, location lLocation)
{
object oAssociate;
int nIndex;
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
{
oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation));
}
for(nIndex = 2; nIndex < 6; nIndex++)
{
oAssociate = GetAssociate(nIndex, oPC);
if(oAssociate != OBJECT_INVALID) AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation));
}
}
void ai_SelectFollowTarget(object oPC, object oAssociate, object oTarget)
{
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
int nToken = NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI);
float fRange = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE) +
StringToFloat(Get2DAString("appearance", "PREFATCKDIST", GetAppearanceType(oAssociate)));
string sRange = FloatToString(fRange, 0, 0);
if(oAssociate == oTarget)
{
ai_SetAIMode(oAssociate, AI_MODE_FOLLOW, FALSE);
DeleteLocalObject(oAssociate, AI_FOLLOW_TARGET);
string sTarget;
if(ai_GetIsCharacter(oAssociate))
{
sTarget = "nobody";
ai_SendMessages(GetName(oAssociate) + " is not following anyone now!", AI_COLOR_YELLOW, oPC);
}
else
{
sTarget = GetName(oPC);
ai_SendMessages(GetName(oAssociate) + " is now following " + sTarget + "!", AI_COLOR_YELLOW, oPC);
}
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_follow_target_tooltip", " " + GetName(oAssociate) + " following " + sTarget + " [" + sRange + " meters]");
}
else
{
ai_SetAIMode(oAssociate, AI_MODE_FOLLOW, TRUE);
SetLocalObject(oAssociate, AI_FOLLOW_TARGET, oTarget);
ai_SendMessages(GetName(oAssociate) + " is now following " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC);
AssignCommand(oAssociate, ActionMoveToObject(oTarget, TRUE, ai_GetFollowDistance(oAssociate)));
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_follow_target_tooltip", " " + GetName(oAssociate) + " following " + GetName(oTarget) + " [" + sRange + " meters]");
}
aiSaveAssociateModesToDb(oPC, oAssociate);
}
void ai_OriginalRemoveAllActionMode(object oPC)
{
if(!ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST)) return;
object oAssociate;
int nIndex;
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
{
oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
if(oAssociate != OBJECT_INVALID &&
!ai_GetAIMode(oAssociate, AI_MODE_GHOST) &&
GetLocalInt(oAssociate, sGhostModeVarname))
{
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
DeleteLocalInt(oAssociate, sGhostModeVarname);
}
}
for(nIndex = 2; nIndex < 6; nIndex++)
{
oAssociate = GetAssociate(nIndex, oPC);
if(oAssociate != OBJECT_INVALID &&
!ai_GetAIMode(oAssociate, AI_MODE_GHOST) &&
GetLocalInt(oAssociate, sGhostModeVarname))
{
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
DeleteLocalInt(oAssociate, sGhostModeVarname);
}
}
}
void ai_RemoveAllActionMode(object oPC)
{
object oAssociate;
int nIndex;
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
{
oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
if(oAssociate != OBJECT_INVALID)
{
ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, FALSE);
if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) &&
!ai_GetAIMode(oAssociate, AI_MODE_GHOST) &&
GetLocalInt(oAssociate, sGhostModeVarname))
{
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
DeleteLocalInt(oAssociate, sGhostModeVarname);
}
ExecuteScript("nw_ch_ac1", oAssociate);
}
}
for(nIndex = 2; nIndex < 6; nIndex++)
{
oAssociate = GetAssociate(nIndex, oPC);
if(oAssociate != OBJECT_INVALID)
{
ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, FALSE);
if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) &&
!ai_GetAIMode(oAssociate, AI_MODE_GHOST) &&
GetLocalInt(oAssociate, sGhostModeVarname))
{
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
DeleteLocalInt(oAssociate, sGhostModeVarname);
}
ExecuteScript("nw_ch_ac1", oAssociate);
}
}
}
void ai_SelectTrap(object oPC, object oAssociate, object oItem)
{
if(GetBaseItemType(oItem) != BASE_ITEM_TRAPKIT)
{
ai_SendMessages("A trap kit was not selected.", AI_COLOR_YELLOW, oPC);
return;
}
ai_SendMessages("Now select a location to place the trap.", AI_COLOR_YELLOW, oPC);
SetLocalObject(oAssociate, "AI_TRAP_KIT", oItem);
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_PLACE_TRAP");
OpenInventory(oAssociate, oPC);
EnterTargetingMode(oPC, OBJECT_TYPE_TILE, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
}
void ai_PlaceTrap(object oPC, location lLocation)
{
object oItem = GetLocalObject(OBJECT_SELF, "AI_TRAP_KIT");
itemproperty ipTrap = GetFirstItemProperty(oItem);
if(GetItemPropertyType(ipTrap) == ITEM_PROPERTY_TRAP)
{
ActionUseItemAtLocation(oItem, ipTrap, lLocation);
}
else ai_SendMessages("This trap kit does not have a trap property!", AI_COLOR_YELLOW, oPC);
}
void ai_AddToGroup(object oDM, object oTarget, string sTargetMode)
{
string sGroup = GetStringRight(sTargetMode, 1);
if(oDM == oTarget)
{
ai_SendMessages("Group " + sGroup + " has been cleared.", AI_COLOR_YELLOW, oDM);
string sText = "Group " + sGroup;
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText + " (Left Action/Right Add)"));
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText + " (Left Action/Right Add)"));
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_label", JsonString(sText));
DeleteLocalJson(oDM, "DM_GROUP" + sGroup);
return;
}
string sName = GetName(oTarget);
json jGroup = GetLocalJson(oDM, "DM_GROUP" + sGroup);
if(JsonGetType(jGroup) == JSON_TYPE_NULL)
{
string sText = sName + "'s group";
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText + " [Run]"));
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText + " [Run]"));
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_label", JsonString(sText));
jGroup = JsonArrayInsert(JsonArray(), JsonInt(1));
}
string sUUID = GetObjectUUID(oTarget);
int nIndex = 1;
string sListUUID = JsonGetString(JsonArrayGet(jGroup, nIndex));
while(sListUUID != "")
{
if(sListUUID == sUUID)
{
ai_SendMessages("This creature is already in the group!", AI_COLOR_RED, oDM);
return;
}
sListUUID = JsonGetString(JsonArrayGet(jGroup, ++nIndex));
}
jGroup = JsonArrayInsert(jGroup, JsonString(sUUID));
ai_SendMessages(sName + " has been saved to group" + sGroup, AI_COLOR_YELLOW, oDM);
SetLocalJson(oDM, "DM_GROUP" + sGroup, jGroup);
EnterTargetingMode(oDM, OBJECT_TYPE_CREATURE, MOUSECURSOR_PICKUP, MOUSECURSOR_PICKUP_DOWN);
}
void ai_MonsterAction(object oDM, object oTarget, location lLocation, int bRun, int nIndex)
{
object oCreature = OBJECT_SELF;
int nObjectType = GetObjectType(oTarget);
ai_ClearCreatureActions(TRUE);
if(oTarget == GetArea(oDM))
{
ActionMoveToLocation(lLocation, bRun);
}
else if(nObjectType == OBJECT_TYPE_CREATURE)
{
if(GetIsDead(oTarget)) return;
else if(GetIsEnemy(oTarget, oCreature))
{
// Lock them into attacking this target only.
SetLocalObject(oCreature, AI_PC_LOCKED_TARGET, oTarget);
// This resets a creatures failed Moral save in combat.
if(GetLocalString(oCreature, AI_COMBAT_SCRIPT) == "ai_coward")
{
SetLocalString(oCreature, AI_COMBAT_SCRIPT, GetLocalString(oCreature, AI_DEFAULT_SCRIPT));
}
if(ai_GetIsInCombat(oCreature)) ai_DoMonsterCombatRound(oCreature);
else
{
ai_HaveCreatureSpeak(oCreature, 5, ":0:1:2:3:6:");
ai_StartMonsterCombat(oCreature);
}
if(nIndex == 1)
{
ai_SendMessages(GetName(oCreature) + "'s group is attacking " + GetName(oTarget), AI_COLOR_RED, oDM);
}
}
else if(oTarget == oDM)
{
if(GetLocalInt(oCreature, "AI_FOLLOWING_DM"))
{
ClearAllActions(FALSE, oCreature);
DeleteLocalInt(oCreature, "AI_FOLLOWING_DM");
if(nIndex == 1)
{
ai_SendMessages(GetName(oCreature) + "'s group has stopped following you.", AI_COLOR_RED, oDM);
}
}
else
{
ActionForceFollowObject(oDM, 4.0);
SetLocalInt(oCreature, "AI_FOLLOWING_DM", TRUE);
if(nIndex == 1)
{
ai_SendMessages(GetName(oCreature) + "'s group is following you.", AI_COLOR_RED, oDM);
}
}
}
else
{
ActionMoveToObject(oTarget, TRUE);
// Player will be stuck with this variable if they are not using the AI.
DeleteLocalInt(oTarget, "AI_I_AM_BEING_HEALED");
ActionDoCommand(ai_ActionTryHealing(oCreature, oTarget));
if(nIndex == 1)
{
ai_SendMessages(GetName(oCreature) + "'s group is moving to and attempting to heal " + GetName(oTarget), AI_COLOR_RED, oDM);
}
}
}
else if(nObjectType == OBJECT_TYPE_DOOR)
{
if(GetIsTrapped(oTarget))
{
if(GetTrapDetectedBy(oTarget, oDM)) SetTrapDetectedBy(oTarget, oCreature);
if(GetTrapDetectedBy(oTarget, oCreature))
{
ai_ReactToTrap(oCreature, oTarget, TRUE);
EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
else if(GetLocked(oTarget)) ai_AttemptToByPassLock(oCreature, oTarget);
}
else if(GetLocked(oTarget)) ai_AttemptToByPassLock(oCreature, oTarget);
else if(GetIsOpen(oTarget))
{
ActionCloseDoor(oTarget, TRUE);
}
else ActionOpenDoor(oTarget, TRUE);
}
else if(nObjectType == OBJECT_TYPE_ITEM)
{
ActionPickUpItem(oTarget);
}
else if(nObjectType == OBJECT_TYPE_PLACEABLE)
{
ActionMoveToObject(oTarget, TRUE);
if(GetHasInventory(oTarget))
{
if(GetIsTrapped(oTarget))
{
if(GetTrapDetectedBy(oTarget, oDM)) SetTrapDetectedBy(oTarget, oCreature);
if(GetTrapDetectedBy(oTarget, oCreature))
{
ai_ReactToTrap(oCreature, oTarget, TRUE);
EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
if(GetLocked(oTarget))
{
if(!ai_AttemptToByPassLock(oCreature, oTarget))
{
AssignCommand(oCreature, ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oTarget) + " is locked!"));
}
EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE);
}
else if(GetLocked(oTarget))
{
if(ai_AttemptToByPassLock(oCreature, oTarget))
{
AssignCommand(oCreature, ai_HaveCreatureSpeak(oCreature, 0, "This " + GetName(oTarget) + " is locked!"));
}
EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
ActionDoCommand(ai_SearchObject(oCreature, oTarget, oDM, TRUE));
}
DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE);
}
else if(nObjectType == OBJECT_TYPE_TRIGGER)
{
if(GetIsTrapped(oTarget))
{
if(GetTrapDetectedBy(oTarget, oDM)) SetTrapDetectedBy(oTarget, oCreature);
if(GetTrapDetectedBy(oTarget, oCreature)) ai_ReactToTrap(oCreature, oTarget, TRUE);
}
}
EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
}
void ai_DMAction(object oDM, object oTarget, location lLocation, string sTargetMode)
{
string sGroup = GetStringRight(sTargetMode, 1);
json jGroup = GetLocalJson(oDM, "DM_GROUP" + sGroup);
int bRun = JsonGetInt(JsonArrayGet(jGroup, 0));
int nIndex = 1;
string sUUID = JsonGetString(JsonArrayGet(jGroup, nIndex));
object oCreature;
while(sUUID != "")
{
oCreature = GetObjectByUUID(sUUID);
AssignCommand(oCreature, ai_MonsterAction(oDM, oTarget, lLocation, bRun, nIndex));
sUUID = JsonGetString(JsonArrayGet(jGroup, ++nIndex));
}
if(nIndex == 0) ai_SendMessages("Group" + sGroup + " is empty!", AI_COLOR_RED, oDM);
}
void ai_SelectWidgetSpellTarget(object oPC, object oAssociate, string sElem)
{
int nIndex;
if(GetStringLength(sElem) == 13) nIndex = StringToInt(GetStringRight(sElem, 2));
else nIndex = StringToInt(GetStringRight(sElem, 1));
SetLocalInt(oAssociate, "AI_WIDGET_SPELL_INDEX", nIndex);
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata");
json jSpells = JsonArrayGet(jAIData, 10);
json jWidget = JsonArrayGet(jSpells, 2);
json jSpell = JsonArrayGet(jWidget, nIndex);
int nSpell = JsonGetInt(JsonArrayGet(jSpell, 0));
int nClass = JsonGetInt(JsonArrayGet(jSpell, 1));
if(nClass == -1) // This is an Item.
{
object oItem = GetObjectByUUID(JsonGetString(JsonArrayGet(jSpell, 5)));
int nBaseItemType = GetBaseItemType(oItem);
if(Get2DAString("spells", "Range", nSpell) == "P" || // Self
nBaseItemType == BASE_ITEM_ENCHANTED_POTION ||
nBaseItemType == BASE_ITEM_POTIONS)
{
int nIprpSubType = JsonGetInt(JsonArrayGet(jSpell, 4));
itemproperty ipProperty = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipProperty))
{
if(nIprpSubType == GetItemPropertySubType(ipProperty)) break;
ipProperty = GetNextItemProperty(oItem);
}
if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE));
AssignCommand(oAssociate, ActionUseItemOnObject(oItem, ipProperty, oAssociate));
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
return;
}
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_USE_ITEM");
if(nSpell == SPELL_HEALINGKIT)
{
EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_MAGIC, MOUSECURSOR_NOMAGIC);
return;
}
}
else // Feats, Spells, Special Abilities.
{
int nFeat = JsonGetInt(JsonArrayGet(jSpell, 5));
if(nFeat)
{
if(!nSpell || Get2DAString("spells", "Range", nSpell) == "P" || // Self
nFeat == FEAT_SUMMON_FAMILIAR || nFeat == FEAT_ANIMAL_COMPANION ||
nFeat == FEAT_TURN_UNDEAD)
{
if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE));
// Adjust the spell used for wild shape and other shape feats.
if(nFeat == FEAT_WILD_SHAPE) nSpell += 607;
if(nFeat == FEAT_ELEMENTAL_SHAPE)
{
if(nSpell == 397) nSpell == SUBFEAT_ELEMENTAL_SHAPE_FIRE;
else if(nSpell == 398) nSpell == SUBFEAT_ELEMENTAL_SHAPE_WATER;
else if(nSpell == 399) nSpell == SUBFEAT_ELEMENTAL_SHAPE_EARTH;
else if(nSpell == 400) nSpell == SUBFEAT_ELEMENTAL_SHAPE_AIR;
}
// Do special targeting for attack feats.
if(nFeat == FEAT_STUNNING_FIST || nFeat == FEAT_DIRTY_FIGHTING ||
nFeat == FEAT_WHIRLWIND_ATTACK || nFeat == FEAT_QUIVERING_PALM ||
nFeat == FEAT_KNOCKDOWN || nFeat == FEAT_IMPROVED_KNOCKDOWN ||
nFeat == FEAT_SAP || nFeat == FEAT_KI_DAMAGE ||
nFeat == FEAT_DISARM || nFeat == FEAT_IMPROVED_DISARM ||
nFeat == FEAT_SMITE_EVIL || nFeat == FEAT_SMITE_GOOD)
{
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_USE_FEAT");
SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate);
EnterTargetingMode(oPC, OBJECT_TYPE_CREATURE, MOUSECURSOR_ATTACK, MOUSECURSOR_NOATTACK);
}
// Check feat and adjust if it is an action mode feat.
if(ai_SetActionMode(oAssociate, nFeat)) return;
AssignCommand(oAssociate, ActionUseFeat(nFeat, oAssociate, nSpell));
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
return;
}
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_USE_FEAT");
}
else SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_CAST_SPELL");
}
SetLocalObject(oPC, AI_TARGET_ASSOCIATE, oAssociate);
int nObjectType;
string sTarget = Get2DAString("spells", "TargetType", nSpell);
int nTarget = ai_HexStringToInt(sTarget);
//SendMessageToPC(GetFirstPC(), "nTarget: " + IntToString(nTarget));
if((nTarget & 1) && !(nTarget & 2) &&!(nTarget & 4))
{
if(ai_GetIsInCombat(oAssociate)) AssignCommand(oAssociate, ai_ClearCreatureActions(TRUE));
ai_CastWidgetSpell(oPC, oAssociate, oAssociate, GetLocation(oAssociate));
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
return;
}
if((nTarget & 1) || (nTarget & 2)) nObjectType += OBJECT_TYPE_CREATURE;
if(nTarget & 4) nObjectType += OBJECT_TYPE_TILE;
if(nTarget & 8) nObjectType += OBJECT_TYPE_ITEM;
if(nTarget & 16) nObjectType += OBJECT_TYPE_DOOR;
if(nTarget & 32) nObjectType += OBJECT_TYPE_PLACEABLE;
if(nTarget & 64) nObjectType += OBJECT_TYPE_TRIGGER;
string sShape = Get2DAString("spells", "TargetShape", nSpell);
int nShape, nSetData;
float fRange;
if(oPC == oAssociate)
{
nSetData = TRUE;
fRange = ai_GetSpellRange(nSpell);
if(fRange == 0.1) fRange = 0.0;
}
if(sShape == "sphere")
{
nShape = SPELL_TARGETING_SHAPE_SPHERE;
nSetData = TRUE;
}
else if(sShape == "rectangle")
{
nShape = SPELL_TARGETING_SHAPE_RECT;
nSetData = TRUE;
}
else if(sShape == "hsphere")
{
nShape = SPELL_TARGETING_SHAPE_HSPHERE;
nSetData = TRUE;
}
else if(sShape == "cone") nShape = SPELL_TARGETING_SHAPE_CONE;
else nShape = SPELL_TARGETING_SHAPE_NONE;
if(nSetData)
{
float fSizeX = StringToFloat(Get2DAString("spells", "TargetSizeX", nSpell));
float fSizeY = StringToFloat(Get2DAString("spells", "TargetSizeY", nSpell));
int nFlags = StringToInt(Get2DAString("spells", "TargetFlags", nSpell));
SetEnterTargetingModeData(oPC, nShape, fSizeX, fSizeY, nFlags, fRange);
}
EnterTargetingMode(oPC, nObjectType, MOUSECURSOR_MAGIC, MOUSECURSOR_NOMAGIC);
}
void ai_UpdateAssociateWidget(object oPC, object oAssociate)
{
int nUIToken = NuiFindWindow(oPC, ai_GetAssociateType(oPC, oAssociate) + AI_WIDGET_NUI);
if(nUIToken)
{
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
/* Not sure why I did this?
if(oPC != oAssociate)
{
nUIToken = NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI);
if(nUIToken)
{
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
}
} */
}
}
int ai_SetActionMode(object oAssociate, int nFeat)
{
int nMode;
if(nFeat == FEAT_POWER_ATTACK) nMode = ACTION_MODE_POWER_ATTACK;
else if(nFeat == FEAT_RAPID_SHOT) nMode = ACTION_MODE_RAPID_SHOT;
else if(nFeat == FEAT_FLURRY_OF_BLOWS) nMode = ACTION_MODE_FLURRY_OF_BLOWS;
else if(nFeat == FEAT_IMPROVED_POWER_ATTACK) nMode = ACTION_MODE_IMPROVED_POWER_ATTACK;
else if(nFeat == FEAT_EXPERTISE) nMode = ACTION_MODE_EXPERTISE;
else if(nFeat == FEAT_IMPROVED_EXPERTISE) nMode = ACTION_MODE_IMPROVED_EXPERTISE;
else if(nFeat == FEAT_DIRTY_FIGHTING) nMode = ACTION_MODE_DIRTY_FIGHTING;
if(nMode)
{
SetActionMode(oAssociate, nMode, !GetActionMode(oAssociate, nMode));
return TRUE;
}
return FALSE;
}

2157
src/module/nss/0i_spells.nss Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,423 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: 0i_states_cond
//////////////////////////////////////////////////////////////////////////////////////////////////////
Include scripts that handle states and conditions for combat.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_main"
#include "0i_messages"
#include "0i_time"
//#include "X0_I0_COMBAT"
// Wrapper for ClearAllActions - we have added extra vars to be cleared as well.
// Note this references OBJECT_SELF!
void ai_ClearCreatureActions(int bClearCombatState = FALSE);
// Used in combat to keep track of the creatures last rounds action.
// One use is to make sure we don't use the same spell on the next round.
// 0+ is the spell that was cast, other actions use AI_LAST_ACTION_* constants.
void ai_SetLastAction(object oCreature, int nAction = AI_LAST_ACTION_NONE);
// Returns TRUE if oCreatures last rounds action is equal to nAction.
// 0+ is the spell that was cast, other actions use AI_LAST_ACTION_* constants.
int ai_CompareLastAction(object oCreature, int nAction);
// Sets the correct listen checks on oCreature.
void ai_SetListeningPatterns(object oCreature);
// Returns TRUE if oCreature is an elemental, undead, or golem i.e. non-living.
int ai_IsNonliving(int nRacialType);
// Returns TRUE if oCreature is in combat.
int ai_GetIsInCombat(object oCreature);
// Sets the time that this oCreature's current combat round started.
// Using action based combat rounds has an unfortunate side effect:
// Once you attack in melee you will continue to attack in melee do to hardcoded
// logic. This will "PUSH" your end of round back until it decides to stop attacking!
// We avoid this by setting the time and if we check for combat and 6 seconds has
// passed then we assume the current round is over, ClearAllActions, and start the next round.
void ai_SetCombatRound(object oCreature);
// Clears the current combat round timer by deleting the value.
void ai_EndCombatRound(object oCreature);
// Returns TRUE if AI_COMBAT_ROUND_IN_SECONDS has not passed since ai_SetCombatRound.
// If it returns FALSE then it will clear the current combat round timer.
int ai_IsInCombatRound(object oCreature, int nCombatRound = AI_COMBAT_ROUND_IN_SECONDS);
// Returns TRUE if oCreature is busy.
// This checks various actions to see if oCreature is busy;
// in combat, busy mode, Actions: attacking, casting spell, counterspelling,
// disabling trap, item casting spell, opening lock, resting, setting trap.
int ai_GetIsBusy(object oCreature);
// Returns a value based on the disabling effect.
// Dead = 1, Bleeding = 2, Dying = 2, Stunned = 29, Confused = 24, Paralyzed = 27
// Frightened 25, Turned = 35, Petrified = 79, Charmed = 23, Disappearappear = 75,
// Time Stop = 66, Dazed = 28, Sleep = 30.
// Returns FALSE if not Disabled.
int ai_Disabled(object oCreature);
// Set one of the AI_MODE_* bitwise constants on oAssociate to bOn.
void ai_SetAIMode(object oAssociate, int nBit, int bOn = TRUE);
// Return if nMode is set on oAssociate. Uses the AI_MODE_* bitwise constants.
int ai_GetAIMode(object oAssociate, int nBit);
// Set one of the AI_MAGIC_* bitwise constants on oAssociate to bOn.
void ai_SetMagicMode(object oAssociate, int nBit, int bOn = TRUE);
// Return if nMode is set on oAssociate. Uses the AI_MAGIC_* bitwise constants.
int ai_GetMagicMode(object oAssociate, int nBit);
// This is based off of the PC's settings for an associate and other creatures use a default.
// Set one of the AI_LOOT_* bitwise constants on oAssociate to bOn.
void ai_SetLootFilter(object oAssociate, int nBit, int bOn = TRUE);
// Return if nMode is set on oAssociate. Uses the AI_LOOT_* bitwise constants.
int ai_GetLootFilter(object oAssociate, int nBit);
// Set one of the AI_IP_* bitwise constants on oCreature to bOn.
void ai_SetItemProperty(object oCreature, string sVarname, int nBit, int bOn = TRUE);
// Return if nMode is set on oCreature. Uses the AI_IP_* bitwise constants.
int ai_GetItemProperty(object oCreature, string sVarname, int nBit);
// Returns the number of hitpoints a creature must have to not be healed.
// This is based off of the PC's settings for an associate and other creatures use a default.
int ai_GetHealersHpLimit(object oCreature, int bInCombat = TRUE);
// Returns TRUE if nCondition is within nCurrentConditions.
// nCurrentConditions is setup in ai_GetNegativeConditions.
int ai_GetHasNegativeCondition(int nCondition, int nCurrentConditions);
// Returns an integer with bitwise flags set that represent the current negative
// conditions on oCreature. ai_GetHasNegativeCondition uses this function.
int ai_GetNegativeConditions(object oCreature);
// Returns TRUE if oObject is in the line of sight of oCreature.
// If the creature is close LineOfSight doesn't work well.
int ai_GetIsInLineOfSight(object oCreature, object oObject);
// Add the specified condition flag to the behavior state of the caller
void ai_SetBehaviorState(int nCondition, int bValid = TRUE);
// Returns TRUE if the specified behavior flag is set on the caller
int ai_GetBehaviorState(int nCondition);
// Highlights the current mode for the widget passed.
void ai_HighlightWidgetMode(object oPC, object oAssociate, int nToken);
// Checks to see if the party scale is correctly adjusted.
void ai_CheckXPPartyScale(object oCreature);
void ai_ClearCreatureActions(int bClearCombatState = FALSE)
{
if(AI_DEBUG) ai_Debug("0i_states_cond", "89", GetName(OBJECT_SELF) + " is clearing actions (" +
IntToString(bClearCombatState) + ")!");
DeleteLocalInt(OBJECT_SELF, AI_CURRENT_ACTION_MODE);
ClearAllActions(bClearCombatState);
}
void ai_SetLastAction(object oCreature, int nAction = AI_LAST_ACTION_NONE)
{
SetLocalInt(oCreature, sLastActionVarname, nAction);
}
int ai_CompareLastAction(object oCreature, int nAction)
{
// Are we checking to see if we cast a spell?
if(nAction == AI_LAST_ACTION_CAST_SPELL &&
GetLocalInt(oCreature, sLastActionVarname) > -1) return TRUE;
// Check other last actions.
return (nAction == GetLocalInt(oCreature, sLastActionVarname));
}
void ai_SetListeningPatterns(object oCreature)
{
SetListenPattern(oCreature, AI_I_SEE_AN_ENEMY, AI_ALLY_SEES_AN_ENEMY);
SetListenPattern(oCreature, AI_I_HEARD_AN_ENEMY, AI_ALLY_HEARD_AN_ENEMY);
SetListenPattern(oCreature, AI_ATKED_BY_WEAPON, AI_ALLY_ATKED_BY_WEAPON);
SetListenPattern(oCreature, AI_ATKED_BY_SPELL, AI_ALLY_ATKED_BY_SPELL);
SetListenPattern(oCreature, AI_I_AM_WOUNDED, AI_ALLY_IS_WOUNDED);
SetListenPattern(oCreature, AI_I_AM_DEAD, AI_ALLY_IS_DEAD);
SetListenPattern(oCreature, AI_I_AM_DISEASED, AI_ALLY_IS_DISEASED);
SetListenPattern(oCreature, AI_I_AM_POISONED, AI_ALLY_IS_POISONED);
SetListenPattern(oCreature, AI_I_AM_WEAK, AI_ALLY_IS_WEAK);
SetListening(oCreature, TRUE);
}
int ai_IsNonliving(int nRacialType)
{
switch(nRacialType)
{
case RACIAL_TYPE_CONSTRUCT:
case RACIAL_TYPE_ELEMENTAL:
case RACIAL_TYPE_UNDEAD: return TRUE;
}
return FALSE;
}
int ai_GetIsInCombat(object oCreature)
{
if(AI_DEBUG) ai_Debug("0i_states_cond", "110", GetName(oCreature) + " is in Combat: Enemy Numbers = " + IntToString(GetLocalInt(oCreature, AI_ENEMY_NUMBERS)));
return GetLocalInt(oCreature, AI_ENEMY_NUMBERS);
}
void ai_SetCombatRound(object oCreature)
{
SetLocalInt(oCreature, "AI_COMBAT_ROUND_START", SQLite_GetTimeStamp());
if(AI_DEBUG) ai_Debug("0i_states_cond", "116", " ===============> " + GetName(oCreature) + " ROUND START:" + IntToString(SQLite_GetTimeStamp()) + " <===============");
}
void ai_EndCombatRound(object oCreature)
{
if(AI_DEBUG) ai_Debug("0i_states_cond", "120", " ===============> " + GetName(oCreature) + " ROUND END:" + IntToString(SQLite_GetTimeStamp()) + " <===============");
DeleteLocalInt(oCreature, "AI_COMBAT_ROUND_START");
}
int ai_IsInCombatRound(object oCreature, int nCombatRound = AI_COMBAT_ROUND_IN_SECONDS)
{
int nCombatRoundStart = GetLocalInt(oCreature, "AI_COMBAT_ROUND_START");
if(AI_DEBUG) ai_Debug("0i_states_cond", "148", " nCombatRoundStart: " + IntToString(nCombatRoundStart));
if(!nCombatRoundStart) return FALSE;
// New combat round calculator. If 6 seconds has passed then we are on a new round!
int nSQLTime = SQLite_GetTimeStamp();
int nCombatRoundTime = nSQLTime - nCombatRoundStart;
if(AI_DEBUG) ai_Debug("0i_states_cond", "153", " SQLite_GetTimeStamp: " + IntToString(nSQLTime) +
"(" + IntToString(nSQLTime - nCombatRoundStart) + ")");
if(nCombatRoundTime < nCombatRound) return TRUE;
ai_EndCombatRound(oCreature);
return FALSE;
}
// Testing to see if we can fix some delaying in combat.
int ai_GetIsBusy(object oCreature)
{
int nAction = GetCurrentAction(oCreature);
if(AI_DEBUG) ai_Debug("0i_states_cond", "140", GetName(oCreature) + " Get is Busy, action: " +
IntToString(nAction));
switch(nAction)
{
case ACTION_CASTSPELL :
case ACTION_ITEMCASTSPELL :
case ACTION_OPENLOCK :
case ACTION_REST :
case ACTION_DISABLETRAP :
case ACTION_ATTACKOBJECT :
case ACTION_COUNTERSPELL :
case ACTION_SETTRAP : return TRUE;
case ACTION_WAIT :
case ACTION_INVALID :
{
int nCombatWait = GetLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS);
if(AI_DEBUG) ai_Debug("0i_states_cond", "153", "nCombatWait: " + IntToString(nCombatWait) +
" AI_AM_I_SEARCHING: " + IntToString(GetLocalInt(oCreature, AI_AM_I_SEARCHING)));
if(nCombatWait)
{
if(ai_IsInCombatRound(oCreature, nCombatWait)) return TRUE;
DeleteLocalInt(oCreature, AI_COMBAT_WAIT_IN_SECONDS);
}
else if(GetLocalInt(oCreature, AI_AM_I_SEARCHING)) DeleteLocalInt(oCreature, AI_AM_I_SEARCHING);
return FALSE;
}
case ACTION_MOVETOPOINT :
{
return ai_GetIsInCombat(oCreature);
}
}
return FALSE;
}
int ai_Disabled(object oCreature)
{
if(GetIsDead(oCreature)) return 1;
// Check for effects.
effect eEffect = GetFirstEffect(oCreature);
while(GetIsEffectValid(eEffect))
{
switch(GetEffectType(eEffect))
{
case EFFECT_TYPE_DOMINATED :
{
if(!GetCommandable(oCreature)) SetCommandable(TRUE, oCreature);
return FALSE;
}
case EFFECT_TYPE_STUNNED :
case EFFECT_TYPE_DAZED :
case EFFECT_TYPE_SLEEP :
case EFFECT_TYPE_CONFUSED :
case EFFECT_TYPE_FRIGHTENED :
case EFFECT_TYPE_PARALYZE :
case EFFECT_TYPE_TURNED :
case EFFECT_TYPE_CHARMED :
case EFFECT_TYPE_PETRIFY :
case EFFECT_TYPE_TIMESTOP :
{
if(AI_DEBUG) ai_Debug("0i_stats_cond", "195", GetName(oCreature) + " is disabled(" +
IntToString(GetEffectType(eEffect)) + ")");
return GetEffectType(eEffect);
}
}
eEffect = GetNextEffect(oCreature);
}
// Not Commandable is basically disabled as far as the AI is concerned.
if(!GetCommandable(oCreature))
{
if(AI_DEBUG) ai_Debug("0i_stats_cond", "213", GetName(oCreature) + " is disabled(Not Commandable)!");
return EFFECT_TYPE_PARALYZE;
}
if(AI_DEBUG) ai_Debug("0i_states_cond", "202", GetName(oCreature) + " is not disabled.");
return FALSE;
}
void ai_SetAIMode(object oAssociate, int nBit, int bOn = TRUE)
{
int nAIModes = GetLocalInt(oAssociate, sAIModeVarname);
if(bOn) nAIModes = nAIModes | nBit;
else nAIModes = nAIModes & ~nBit;
SetLocalInt(oAssociate, sAIModeVarname, nAIModes);
// Set widget to show the mode they are in.
}
int ai_GetAIMode(object oAssociate, int nBit)
{
if(GetLocalInt(oAssociate, sAIModeVarname) & nBit) return TRUE;
return FALSE;
}
void ai_SetMagicMode(object oAssociate, int nBit, int bOn = TRUE)
{
int nMagicModes = GetLocalInt(oAssociate, sMagicModeVarname);
if(bOn) nMagicModes = nMagicModes | nBit;
else nMagicModes = nMagicModes & ~nBit;
SetLocalInt(oAssociate, sMagicModeVarname, nMagicModes);
}
int ai_GetMagicMode(object oAssociate, int nBit)
{
if(GetLocalInt(oAssociate, sMagicModeVarname) & nBit) return TRUE;
return FALSE;
}
void ai_SetLootFilter(object oAssociate, int nLootBit, int bOn = TRUE)
{
int nLootFilter = GetLocalInt(oAssociate, sLootFilterVarname);
if(bOn) nLootFilter = nLootFilter | nLootBit;
else nLootFilter = nLootFilter & ~nLootBit;
SetLocalInt(oAssociate, sLootFilterVarname, nLootFilter);
}
int ai_GetLootFilter(object oAssociate, int nBit)
{
if(GetLocalInt(oAssociate, sLootFilterVarname) & nBit) return TRUE;
return FALSE;
}
void ai_SetItemProperty(object oCreature, string sVarname, int nBit, int bOn = TRUE)
{
int nItemProperties = GetLocalInt(oCreature, sVarname);
if(bOn) nItemProperties = nItemProperties | nBit;
else nItemProperties = nItemProperties & ~nBit;
SetLocalInt(oCreature, sVarname, nItemProperties);
}
int ai_GetItemProperty(object oCreature, string sVarname, int nBit)
{
if(GetLocalInt(oCreature, sVarname) & nBit) return TRUE;
return FALSE;
}
int ai_GetHealersHpLimit(object oCreature, int bInCombat = TRUE)
{
if(bInCombat) return GetLocalInt(oCreature, AI_HEAL_IN_COMBAT_LIMIT);
else return GetLocalInt(oCreature, AI_HEAL_OUT_OF_COMBAT_LIMIT);
}
int ai_GetHasNegativeCondition(int nCondition, int nCurrentConditions)
{
return (nCurrentConditions & nCondition);
}
int ai_GetNegativeConditions(object oCreature)
{
int nCondition, nEffectType;
effect eEffect = GetFirstEffect(oCreature);
while(GetIsEffectValid (eEffect))
{
// Rage and maybe other abilities might come from the oCreature!
if(GetEffectCreator(eEffect) != oCreature)
{
nEffectType = GetEffectType(eEffect);
switch(nEffectType)
{
case EFFECT_TYPE_DISEASE: nCondition = nCondition | AI_CONDITION_DISEASE; break;
case EFFECT_TYPE_POISON: nCondition = nCondition | AI_CONDITION_POISON; break;
case EFFECT_TYPE_CURSE: nCondition = nCondition | AI_CONDITION_CURSE; break;
case EFFECT_TYPE_BLINDNESS:
case EFFECT_TYPE_DEAF: nCondition = nCondition | AI_CONDITION_BLINDDEAF; break;
case EFFECT_TYPE_ABILITY_DECREASE: nCondition = nCondition | AI_CONDITION_ABILITY_DRAIN; break;
case EFFECT_TYPE_NEGATIVELEVEL: nCondition = nCondition | AI_CONDITION_LEVEL_DRAIN; break;
case EFFECT_TYPE_AC_DECREASE: nCondition = nCondition | AI_CONDITION_AC_DECREASE; break;
case EFFECT_TYPE_ATTACK_DECREASE: nCondition = nCondition | AI_CONDITION_ATK_DECREASE; break;
case EFFECT_TYPE_CHARMED: nCondition = nCondition | AI_CONDITION_CHARMED; break;
case EFFECT_TYPE_CONFUSED: nCondition = nCondition | AI_CONDITION_CONFUSED; break;
case EFFECT_TYPE_DAZED: nCondition = nCondition | AI_CONDITION_DAZED; break;
case EFFECT_TYPE_DAMAGE_DECREASE: nCondition = nCondition | AI_CONDITION_DMG_DECREASE; break;
case EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE: nCondition = nCondition | AI_CONDITION_DMG_I_DECREASE; break;
case EFFECT_TYPE_DOMINATED: nCondition = nCondition | AI_CONDITION_DOMINATED; break;
case EFFECT_TYPE_FRIGHTENED: nCondition = nCondition | AI_CONDITION_FRIGHTENED; break;
case EFFECT_TYPE_PARALYZE: nCondition = nCondition | AI_CONDITION_PARALYZE; break;
case EFFECT_TYPE_SAVING_THROW_DECREASE: nCondition = nCondition | AI_CONDITION_SAVE_DECREASE; break;
case EFFECT_TYPE_SKILL_DECREASE: nCondition = nCondition | AI_CONDITION_SKILL_DECREASE; break;
case EFFECT_TYPE_SLOW: nCondition = nCondition | AI_CONDITION_SLOW; break;
case EFFECT_TYPE_SPELL_RESISTANCE_DECREASE: nCondition = nCondition | AI_CONDITION_SR_DECREASE; break;
case EFFECT_TYPE_STUNNED: nCondition = nCondition | AI_CONDITION_STUNNED; break;
}
}
eEffect = GetNextEffect(oCreature);
}
return nCondition;
}
int ai_GetIsInLineOfSight(object oCreature, object oObject)
{
// Creatures can block the line of sight so when close we shouldn't check.
if(GetDistanceBetween(oObject, oCreature) <= AI_RANGE_MELEE) return TRUE;
return LineOfSightObject(oCreature, oObject);
}
void ai_SetBehaviorState(int nCondition, int bValid = TRUE)
{
int nPlot = GetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER");
if(bValid)
{
nPlot = nPlot | nCondition;
SetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER", nPlot);
}
else
{
nPlot = nPlot & ~nCondition;
SetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER", nPlot);
}
}
int ai_GetBehaviorState(int nCondition)
{
int nPlot = GetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER");
if(nPlot & nCondition) return TRUE;
return FALSE;
}
void ai_HighlightWidgetMode(object oPC, object oAssociate, int nToken)
{
if(oPC == oAssociate) return;
int bBool;
bBool = ai_GetAIMode(oAssociate,AI_MODE_DEFEND_MASTER);
NuiSetBind(oPC, nToken, "btn_cmd_guard_encouraged", JsonBool(bBool));
bBool = ai_GetAIMode(oAssociate,AI_MODE_STAND_GROUND);
NuiSetBind(oPC, nToken, "btn_cmd_hold_encouraged", JsonBool(bBool));
bBool = ai_GetAIMode(oAssociate,AI_MODE_FOLLOW);
NuiSetBind(oPC, nToken, "btn_cmd_follow_encouraged", JsonBool(bBool));
if(!ai_GetAIMode(oAssociate, AI_MODE_DEFEND_MASTER) &&
!ai_GetAIMode(oAssociate, AI_MODE_STAND_GROUND) &&
!ai_GetAIMode(oAssociate, AI_MODE_FOLLOW)) bBool = TRUE;
else bBool = FALSE;
NuiSetBind(oPC, nToken, "btn_cmd_attack_encouraged", JsonBool(bBool));
}
void ai_CheckXPPartyScale(object oCreature)
{
object oModule = GetModule();
if(!GetLocalInt(oModule, AI_RULE_PARTY_SCALE)) return;
object oMaster;
if(!ai_GetIsCharacter(oCreature))
{
oMaster = GetMaster(oCreature);
while(oMaster != OBJECT_INVALID)
{
if(ai_GetIsCharacter(oMaster)) break;
oMaster = GetMaster(oMaster);
}
if(oMaster == OBJECT_INVALID) return;
}
else oMaster = oCreature;
float fDefaultXPScale = IntToFloat(GetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP));
float fPartySize = 4.0;
int nAssociateType, nHenchman, nHenchAssociate;
object oHenchman;
for(nAssociateType = 1; nAssociateType <= 5; nAssociateType++)
{
if(nAssociateType == ASSOCIATE_TYPE_HENCHMAN)
{
for(nHenchman = 1; nHenchman <= AI_MAX_HENCHMAN; nHenchman++)
{
oHenchman = GetAssociate(nAssociateType, oMaster, nHenchman);
if(oHenchman != OBJECT_INVALID)
{
fPartySize += 1.0;
for(nHenchAssociate = 2; nHenchAssociate <= 5; nHenchAssociate++)
{
if(GetAssociate(nHenchAssociate, oHenchman, 1) != OBJECT_INVALID) fPartySize += 1.0;
}
}
}
}
else if(GetAssociate(nAssociateType, oMaster, 1) != OBJECT_INVALID) fPartySize += 1.0;
}
int nXPScale = FloatToInt(fPartySize / 4.0 * fDefaultXPScale);
//SendMessageToPC(oMaster, GetName(oMaster) + " nXPScale = (3 + fPartySize / 4.0 * fDefaultXPScale)" +
// IntToString(nXPScale) + " = (" + FloatToString(fPartySize, 0, 1) + " / 4.0 * " +
// FloatToString(fDefaultXPScale, 0, 1) + ")");
SetModuleXPScale(nXPScale);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
/*//////////////////////////////////////////////////////////////////////////////
// Script Name: 0i_time
////////////////////////////////////////////////////////////////////////////////
Include script for handling all time functions for the server.
Lokey's functions:
int GetPosixTimestamp();
string GetCurrentDateTime();
*///////////////////////////////////////////////////////////////////////////////
// RETURNS a Timestamp in seconds since 1970-01-01.
int GetCurrentTimeInSeconds();
// RETURNS a formated date, good for timestamping logs and text.
string GetCurrentDateTime();
// Sends a server shutdown message 1800 seconds i.e 30 minutes before.
// nDuration is in seconds. i.e. one hours is 3600 defaults to 24 hours (86400).
// Should be put into the servers OnHeartBeat.
void CheckServerShutdownMessage(int nDuration = 86400);
int GetCurrentTimeInSeconds()
{
string stmt = "SELECT strftime('%s','now');";
sqlquery sqlQuery = SqlPrepareQueryObject(GetModule(), stmt);
SqlStep(sqlQuery);
return SqlGetInt(sqlQuery, 0);
}
string GetCurrentDateTime()
{
string stmt = "SELECT datetime('now', 'localtime')";
sqlquery sqlQuery = SqlPrepareQueryObject(GetModule(), stmt);
SqlStep(sqlQuery);
return SqlGetString(sqlQuery, 0);
}
/// @addtogroup time Time
/// @brief Provides various time related functions.
/// @brief Returns the current time formatted according to the provided sqlite date time format string.
/// @param format Format string as used by sqlites STRFTIME().
/// @return The current time in the requested format. Empty string on error.
string SQLite_GetFormattedSystemTime(string format);
/// @return Returns the number of seconds since midnight on January 1, 1970.
int SQLite_GetTimeStamp();
/// @return Returns the number of milliseconds since midnight on January 1, 1970.
int SQLite_GetTimeMilliseconds();
/// @brief A millisecond timestamp
struct SQLite_MillisecondTimeStamp
{
int seconds; ///< Seconds since epoch
int milliseconds; ///< Milliseconds
};
/// @remark For mircosecond timestamps use NWNX_Utility_GetHighResTimeStamp().
/// @return Returns the number of milliseconds since midnight on January 1, 1970.
struct SQLite_MillisecondTimeStamp SQLite_GetMillisecondTimeStamp();
/// @brief Returns the current date.
/// @return The date in the format (mm/dd/yyyy).
string SQLite_GetSystemDate();
/// @brief Returns current time.
/// @return The current time in the format (24:mm:ss).
string SQLite_GetSystemTime();
/// @}
string SQLite_GetFormattedSystemTime(string format)
{
sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME(@format, 'now', 'localtime')");
SqlBindString(query, "@format", format);
SqlStep(query); // sqlite returns NULL for invalid format in STRFTIME()
return SqlGetString(query, 0);
}
int SQLite_GetTimeStamp()
{
sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME('%s', 'now')");
SqlStep(query);
return SqlGetInt(query, 0);
}
int SQLite_GetTimeMillisecond()
{
sqlquery query = SqlPrepareQueryObject(GetModule(), "select cast((julianday('now') - 2440587.5) * 86400 * 1000 as integer)");
SqlStep(query);
return SqlGetInt(query, 0);
}
struct SQLite_MillisecondTimeStamp SQLite_GetMillisecondTimeStamp()
{
sqlquery query = SqlPrepareQueryObject(GetModule(), "SELECT STRFTIME('%s', 'now'), SUBSTR(STRFTIME('%f', 'now'), 4)");
SqlStep(query);
struct SQLite_MillisecondTimeStamp t;
t.seconds = SqlGetInt(query, 0);
t.milliseconds = SqlGetInt(query, 1);
return t;
}
string SQLite_GetSystemDate()
{
return SQLite_GetFormattedSystemTime("%m/%d/%Y");
}
string SQLite_GetSystemTime()
{
return SQLite_GetFormattedSystemTime("%H:%M:%S");
}

View File

@ -0,0 +1,105 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_ambusher
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates to ambush creatures by hiding or turning invisible.
OBJECT_SELF is the creature running the ai.
* This assumes we are not invisible since the ai_a_invisible script should fire if we are.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST);
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "19", GetName(oCreature) + " is using ambusher tactics: " +
" oNearestEnemy: " + GetName(oNearestEnemy) + " fDistance: " +
FloatToString(GetDistanceBetween(oNearestEnemy, oCreature), 0, 2));
if(GetDistanceBetween(oNearestEnemy, oCreature) > AI_RANGE_CLOSE)
{
// Has our master told us to not use magic?
if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC))
{
// If can turn invisible then we should probably do that!
if(ai_UseTalent(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_INVISIBILITY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_INVISIBILITY_SPHERE, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_SANCTUARY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_ETHEREALNESS, oCreature)) return; // Greater Sanctuary
if(ai_UseTalent(oCreature, SPELLABILITY_AS_IMPROVED_INVISIBLITY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELLABILITY_AS_INVISIBILITY, oCreature)) return;
}
}
// Check the battle field to see if anyone see us?
int nEnemyIndex = ai_GetNearestIndexThatSeesUs(oCreature);
// If seen, can we try to hide now?
if(nEnemyIndex)
{
// Check for an attacker and can they see through invisibility?
object oAttacker = ai_GetEnemyAttackingMe(oCreature);
int bCanSeeInvisible;
if(oAttacker != OBJECT_INVALID)
{
bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_SEEINVISIBLE);
if(!bCanSeeInvisible) bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_TRUESEEING);
if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_5_FEET, oCreature);
if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_10_FEET, oCreature);
if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_60_FEET, oCreature);
}
if(!bCanSeeInvisible)
{
if(GetHasFeat(FEAT_HIDE_IN_PLAIN_SIGHT, oCreature))
{
if(!GetActionMode(oCreature, ACTION_MODE_STEALTH))
{
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "55", GetName(oCreature) + " is using hide in plain sight!");
ClearAllActions(TRUE);
SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE);
return;
}
}
// Does not have hide in plain sight.
else
{
string sEnemyIndex = IntToString(nEnemyIndex);
float fEnemyDistance = GetLocalFloat(oCreature, AI_ENEMY_RANGE + sEnemyIndex);
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "66", "fDistance: " + FloatToString(fEnemyDistance, 0, 2));
if(fEnemyDistance > 20.0)
{
int bTried = GetLocalInt(oCreature, AI_TRIED_TO_HIDE);
if(!bTried)
{
// Move away so we can hide.
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "73", GetName(oCreature) + " is trying to move away to hide!");
SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
object oEnemy = GetLocalObject(oCreature, AI_ENEMY + sEnemyIndex);
ActionMoveAwayFromObject(oEnemy, TRUE, AI_RANGE_BATTLEFIELD);
SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3);
return;
}
else SetLocalInt(oCreature, AI_TRIED_TO_HIDE, GetLocalInt(oCreature, AI_TRIED_TO_HIDE) - 1);
}
// We have been seen by an enemy near us so drop stealth.
else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
}
}
// The enemy can see through stealth so lets drop it.
else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
}
// We are not in stealth mode so and no one sees us so lets hide.
else if(!GetActionMode(oCreature, ACTION_MODE_STEALTH))
{
// Use any hiding talents we have
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "97", GetName(oCreature) + " is trying to hide!");
SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE);
SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3);
return;
}
// If we have givin up on stealth do our normal actions.
string sScript = GetLocalString(oCreature, AI_DEFAULT_SCRIPT);
if(sScript == "ai_a_ambusher" || sScript == "") sScript = "ai_a_default";
if(AI_DEBUG) ai_Debug("ai_a_ambusher", "101", "Executing Script: " + sScript);
ExecuteScript(sScript, oCreature);
}

View File

@ -0,0 +1,159 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_atk_casters
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates to the nearest casting creatures.
OBJECT_SELF is the creature running the ai.
Our actions.
1 - Get nearest enemy.
2 - Check for healing and curing first.
3 - Check moral if wounded and this is a simple+ battle.
4 - Check for a magical ranged attack if not in melee and a difficult+ battle.
5 - Check for a buff or summons if this is a difficult+ battle.
6 - Check for a Class ability and an offensive spell if this is a simple+ battle.
7 - Check for a physical attack.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
// ******************* OFFENSIVE AOE TALENTS ***********************
// Check the battlefield for a group of enemies to shoot a big spell at!
// We are checking here since these opportunities are rare and we need
// to take advantage of them as often as possible.
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
}
if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING))
{
// ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************
// Does our master want to be buffed first?
object oTarget = OBJECT_INVALID;
if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return;
if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return;
if(ai_TryDivineMightFeat(oCreature, nInMelee)) return;
}
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TryBarbarianRageFeat(oCreature)) return;
if(ai_TryBardSongFeat(oCreature)) return;
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TrySummonFamiliarTalent(oCreature)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// ************************** CLASS FEATURES ***************************
if(ai_TryTurningTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
int bAlwaysAtk = !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK);
if(AI_DEBUG) ai_Debug("ai_a_atk_casters", "80", "Check for ranged attack on nearest casting enemy!");
// ************************** Ranged feat attacks **************************
if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) &&
!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) &&
ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
// Lets pick off the nearest targets first.
if(!nInMelee)
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, TRUE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
if(AI_DEBUG) ai_Debug("ai_a_atk_casters", "119", "Check for melee attack on nearest enemy!");
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TryWhirlwindFeat(oCreature)) return;
if(ai_TrySneakAttack(oCreature, nInMelee, bAlwaysAtk)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_PERCEPTION, bAlwaysAtk);
if(oTarget == OBJECT_INVALID)
{
object oPCTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET);
if(oPCTarget == OBJECT_INVALID)
{
// Are we in melee? If so try to get the nearest enemy in melee.
if(nInMelee > 0)
{
oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
// If we didn't get a target then get any target within range.
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
}
// If not then lets go find someone to attack!
else
{
// Get the nearest enemy.
oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
// If we didn't get a target then get any target within range.
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
}
}
}
// We might not have a target this is fine as sometimes we don't want to attack!
if(AI_DEBUG) ai_Debug("ai_a_atk_casters", "149", GetName(oTarget) + " is the nearest target for melee combat!");
// If we don't find a target then we don't want to fight anyone!
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
if(AI_DEBUG) ai_Debug("ai_a_atk_casters", "154", "Do melee attack against (caster/nearest): " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, TRUE);
}

View File

@ -0,0 +1,80 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_atk_nearest
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates to the nearest target.
OBJECT_SELF is the creature running the ai.
Our actions.
1 - Get nearest enemy.
2 - Check for healing and curing first.
3 - Check moral if wounded and this is a simple+ battle.
4 - Check for a magical ranged attack if not in melee and a difficult+ battle.
5 - Check for a buff or summons if this is a difficult+ battle.
6 - Check for a Class ability and an offensive spell if this is a simple+ battle.
7 - Check for a physical attack.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
// ******************* OFFENSIVE AOE TALENTS ***********************
// Check the battlefield for a group of enemies to shoot a big spell at!
// We are checking here since these opportunities are rare and we need
// to take advantage of them as often as possible.
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
}
if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING))
{
// ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************
// Does our master want to be buffed first?
object oTarget = OBJECT_INVALID;
if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return;
if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return;
if(ai_TryDivineMightFeat(oCreature, nInMelee)) return;
}
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TryBarbarianRageFeat(oCreature)) return;
if(ai_TryBardSongFeat(oCreature)) return;
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TrySummonFamiliarTalent(oCreature)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// ************************** CLASS FEATURES ***************************
if(ai_TryTurningTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
ai_DoPhysicalAttackOnNearest(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
}

View File

@ -0,0 +1,159 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_atk_warrior
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates to the nearest casting creatures.
OBJECT_SELF is the creature running the ai.
Our actions.
1 - Get nearest enemy.
2 - Check for healing and curing first.
3 - Check moral if wounded and this is a simple+ battle.
4 - Check for a magical ranged attack if not in melee and a difficult+ battle.
5 - Check for a buff or summons if this is a difficult+ battle.
6 - Check for a Class ability and an offensive spell if this is a simple+ battle.
7 - Check for a physical attack.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
// ******************* OFFENSIVE AOE TALENTS ***********************
// Check the battlefield for a group of enemies to shoot a big spell at!
// We are checking here since these opportunities are rare and we need
// to take advantage of them as often as possible.
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
}
if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING))
{
// ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************
// Does our master want to be buffed first?
object oTarget = OBJECT_INVALID;
if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return;
if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return;
if(ai_TryDivineMightFeat(oCreature, nInMelee)) return;
}
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TryBarbarianRageFeat(oCreature)) return;
if(ai_TryBardSongFeat(oCreature)) return;
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TrySummonFamiliarTalent(oCreature)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// ************************** CLASS FEATURES ***************************
if(ai_TryTurningTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
int bAlwaysAtk = !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK);
if(AI_DEBUG) ai_Debug("0i_actions", "496", "Check for ranged attack on nearest casting enemy!");
// ************************** Ranged feat attacks **************************
if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) &&
!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) &&
ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
// Lets pick off the nearest targets first.
if(!nInMelee)
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, TRUE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
if(AI_DEBUG) ai_Debug("ai_a_atk_warrior", "119", "Check for melee attack on nearest enemy!");
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TryWhirlwindFeat(oCreature)) return;
if(ai_TrySneakAttack(oCreature, nInMelee, bAlwaysAtk)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_PERCEPTION, bAlwaysAtk);
if(oTarget == OBJECT_INVALID)
{
object oPCTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET);
if(oPCTarget == OBJECT_INVALID)
{
// Are we in melee? If so try to get the nearest enemy in melee.
if(nInMelee > 0)
{
oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
// If we didn't get a target then get any target within range.
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE, AI_ENEMY, bAlwaysAtk);
}
// If not then lets go find someone to attack!
else
{
// Get the nearest enemy.
oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_WARRIOR, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
// If we didn't get a target then get any target within range.
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_PERCEPTION, AI_ENEMY, bAlwaysAtk);
}
}
}
// We might not have a target this is fine as sometimes we don't want to attack!
if(AI_DEBUG) ai_Debug("ai_a_atk_warrior", "149", GetName(oTarget) + " is the nearest target for melee combat!");
// If we don't find a target then we don't want to fight anyone!
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
if(AI_DEBUG) ai_Debug("ai_a_atk_warrior", "154", "Do melee attack against (caster/nearest): " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, TRUE);
}

View File

@ -0,0 +1,87 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_barbarian
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Barbarian class.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
object oTarget;
if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature))
{
//************************* HEALING & CURES **************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// ************************ CLASS FEATURES *************************
if(ai_TryBarbarianRageFeat(oCreature)) return;
// ************************* SPELL TALENTS *************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// ************************* SPELL TALENTS *************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
// ************************ Ranged feat attacks ************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
}
// *************************** Melee feat attacks **************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TryWhirlwindFeat(oCreature)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,83 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_bard
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Bard class.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// ************************** CLASS FEATURES ***************************
if(ai_TryBardSongFeat(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget = OBJECT_INVALID;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TrySneakAttack(oCreature, nInMelee)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,102 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_cleric
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Cleric class.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
// ************************** CLASS FEATURES ***************************
// Turning is basically a powerful AOE so treat it like one.
if(ai_TryTurningTalent(oCreature)) return;
// ******************* OFFENSIVE AOE TALENTS ***********************
// Check the battlefield for a group of enemies to shoot a big spell at!
// We are checking here since these opportunities are rare and we need
// to take advantage of them as often as possible.
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
}
if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING))
{
// ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************
// Does our master want to be buffed first?
object oTarget = OBJECT_INVALID;
if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return;
if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return;
if(ai_TryDivineMightFeat(oCreature, nInMelee)) return;
}
}
// SIMPLE+ - Offensive talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget = OBJECT_INVALID;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,69 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_cntrspell
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for creatures using the combat mode counter spell.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
// We are not in melee combat then we don't attack.
int bAttack = nInMelee;
if(!bAttack)
{
// If there are no casters, i.e. CLERIC or MAGES in the battle then attack.
struct stClasses stClasses = ai_GetFactionsClasses(oCreature);
if(!stClasses.CLERICS && !stClasses.MAGES) bAttack = TRUE;
}
// If we are not attacking and using magic then setup for counter spelling.
if(!bAttack && !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC))
{
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
if(AI_DEBUG) ai_Debug("ai_a_cntrspell", "30", " Counterspell Mode? " +
IntToString(GetActionMode(OBJECT_SELF, ACTION_MODE_COUNTERSPELL)));
if(!GetActionMode(oCreature, ACTION_MODE_COUNTERSPELL))
{
object oTarget = ai_GetNearestClassTarget(oCreature, AI_CLASS_TYPE_CASTER);
// We can only counter spells from a hasted caster if we are hasted as well.
if(ai_GetHasEffectType(oTarget, EFFECT_TYPE_HASTE) &&
!ai_GetHasEffectType(oCreature, EFFECT_TYPE_HASTE))
{
// If we have haste then we should cast it.
if(GetHasSpell(SPELL_HASTE, oCreature))
{
if(AI_DEBUG) ai_Debug("ai_a_cntrspell", "42", "Opponent is hasted! Casting Haste.");
ActionCastSpellAtObject(SPELL_HASTE, oCreature);
ai_SetLastAction(oCreature, SPELL_HASTE);
return;
}
// If not then we need to go into normal combat.
else
{
if(AI_DEBUG) ai_Debug("ai_cntrspell", "50", "Opponent is hasted! Using ranged AI.");
ExecuteScript("ai_a_ranged");
return;
}
}
if(oTarget != OBJECT_INVALID)
{
// First a good tactic for counter spelling is to be invisible.
if(ai_TryToBecomeInvisible(oCreature)) return;
// If we have attempted to become invisible or are invisible then
// it is time to counter spell.
if(AI_DEBUG) ai_Debug("ai_a_cntrspell", "61", "Setting Counterspell mode!");
ActionCounterSpell(oTarget);
return;
}
}
}
if(AI_DEBUG) ai_Debug("ai_a_cntrspell", "67", "Situation is not good for counterspelling! Using ranged AI.");
ExecuteScript("ai_a_ranged");
}

View File

@ -0,0 +1,80 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_no_modes
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates to not use any combat modes during combat ai.
OBJECT_SELF is the creature running the ai.
Our actions.
1 - Get nearest enemy.
2 - Check for healing and curing first.
3 - Check moral if wounded and this is a simple+ battle.
4 - Check for a magical ranged attack if not in melee and a difficult+ battle.
5 - Check for a buff or summons if this is a difficult+ battle.
6 - Check for a Class ability and an offensive spell if this is a simple+ battle.
7 - Check for a physical attack.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
// ******************* OFFENSIVE AOE TALENTS ***********************
// Check the battlefield for a group of enemies to shoot a big spell at!
// We are checking here since these opportunities are rare and we need
// to take advantage of them as often as possible.
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
}
if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING))
{
// ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************
// Does our master want to be buffed first?
object oTarget = OBJECT_INVALID;
if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return;
if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return;
if(ai_TryDivineMightFeat(oCreature, nInMelee)) return;
}
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TryBarbarianRageFeat(oCreature)) return;
if(ai_TryBardSongFeat(oCreature)) return;
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TrySummonFamiliarTalent(oCreature)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// ************************** CLASS FEATURES ***************************
if(ai_TryTurningTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
ai_DoPhysicalAttackOnBest(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
}

View File

@ -0,0 +1,77 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_defensive
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates put in to a defensive mode to protect themselves.
OBJECT_SELF is the creature running the ai.
Our actions.
1 - Get nearest enemy and the difficulty of the battle.
2 - Check for healing potions if this is a simple+ battle.
3 - Check moral if wounded and is a simple+ battle.
4 - Check for a magical ranged attack if not in melee and a difficult+ battle.
5 - Check for a buff if this is a difficult+ battle.
6 - Check for defensive ability such as knockdown, expertise or parry.
7 - If we can't fight defensive then flee.
8 - If we are out of range with no ability then stand and watch.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST);
if(AI_DEBUG) ai_Debug("ai_a_defensive", "25", "oNearest Enemy: " + GetName(oNearestEnemy) +
" Distance to Nearest Enemy: " + FloatToString(GetDistanceToObject(oNearestEnemy), 0, 2));
// ALWAYS - Check for healing and cure talents.
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// SIMPLE+ - Check for moral and get what spell power we should be using.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// DIFFICULT+ - Class talents, Offensive AOE's, Defensive talents, and Potion talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TryBardSongFeat(oCreature)) return;
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TrySummonFamiliarTalent(oCreature)) return;
if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING))
{
// ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ****************
// Does our master want to be buffed first?
object oTarget = OBJECT_INVALID;
if (ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
int nRound = ai_GetCurrentRound(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound, oTarget)) return;
}
}
object oTarget;
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
if(nInMelee > 0)
{
if(ai_TryImprovedExpertiseFeat(oCreature)) return;
if(ai_TryExpertiseFeat(oCreature)) return;
// Lets get the strongest melee opponent in melee with us.
oTarget = ai_GetHighestCRTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = oNearestEnemy;
// Use knockdown when appropriate and the target is not immune.
if(ai_TryKnockdownFeat(oCreature, oTarget)) return;
if (ai_TryParry (oCreature)) return;
// We have tried everything to protect ourselves so the only thing left
// to do is man up and attack!
ai_DoPhysicalAttackOnLowestCR(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
return;
}
//********************** PHYSICAL ATTACKS ********************************
// Even in defensive mode we want to be in battle so go find someone!
ai_DoPhysicalAttackOnBest(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
}

View File

@ -0,0 +1,86 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_druid
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Druid class.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// ************************** CLASS FEATURES ***************************
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TryPolymorphSelfFeat(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
// ************************** Ranged feat attacks **************************
object oTarget;
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,82 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: 0i_a_fighter
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Fighter class.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget = OBJECT_INVALID;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TryWhirlwindFeat(oCreature)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,117 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_flanker
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates to flank the enemy and not charge into combat.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TryBarbarianRageFeat(oCreature)) return;
if(ai_TryBardSongFeat(oCreature)) return;
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TrySummonFamiliarTalent(oCreature)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
oTarget = GetLocalObject(oCreature, AI_PC_LOCKED_TARGET);
// ************************** Melee feat attacks *************************
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
// Lets get the nearest target that is attacking someone besides me. We want to flank!
if(oTarget == OBJECT_INVALID)
{
if(!nInMelee) oTarget = ai_GetFlankTarget(oCreature);
// If there are few enemies then we can safely move around.
else if(nInMelee < 3 || ai_CanIMoveInCombat(oCreature))
{
oTarget = ai_GetFlankTarget(oCreature, AI_RANGE_MELEE);
}
// Ok we are in a serious fight so lets not give attack of opportunities.
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
}
// If there are no enemies being attacked then lets stay back.
if(oTarget == OBJECT_INVALID)
{
if(nInMelee)
{
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
// Lets get the strongest melee opponent in melee with us.
object oTarget = ai_GetHighestCRTargetForMeleeCombat(oCreature, nInMelee);
if(oTarget != OBJECT_INVALID)
{
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
return;
}
}
// ************************** Ranged feat attacks **************************
else if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
oTarget = ai_GetLowestCRTarget(oCreature);
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
else
{
ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE);
return;
}
}
}
if(oTarget != OBJECT_INVALID)
{
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
return;
}
// Are we too far from our master?
object oMaster = GetMaster();
if(GetDistanceBetween(oMaster, oCreature) > AI_RANGE_LONG)
{
ActionMoveToObject(oMaster, TRUE, AI_RANGE_CLOSE);
return;
}
ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE);
}

View File

@ -0,0 +1,123 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_invisible
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates to use when they are invisible.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
// Has our master told us to not use magic?
int bUseMagic = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_EASY)
{
// *************************** SPELL TALENTS ***************************
if(ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING)) return;
// ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************
// Does our master want to be buffed first?
object oTarget = OBJECT_INVALID;
if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
int nRound = ai_GetCurrentRound(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound, oTarget)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TrySummonFamiliarTalent(oCreature)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
// ******************* OFFENSIVE AOE TALENTS ***********************
// Check the battlefield for a group of enemies to shoot a big spell at!
// We are checking here since these opportunities are rare and we need
// to take advantage of them as often as possible.
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
}
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
// ************************** Melee feat attacks *************************
// If we won't loose invisibility then ranged attacks are ok!
// ************************ RANGED ATTACKS *******************************
if(GetHasSpellEffect(SPELL_IMPROVED_INVISIBILITY) || GetHasSpellEffect(SPELLABILITY_AS_IMPROVED_INVISIBLITY))
{
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
}
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TrySneakAttack(oCreature, nInMelee)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee);
if(oTarget != OBJECT_INVALID)
{
talent tUse = GetCreatureTalentBest(TALENT_CATEGORY_HARMFUL_MELEE, 20, oCreature);
if(GetIsTalentValid(tUse))
{
int nId = GetIdFromTalent(tUse);
if(nId == FEAT_POWER_ATTACK) { if(ai_TryPowerAttackFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_KNOCKDOWN) { if(ai_TryKnockdownFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_SMITE_EVIL) { if(ai_TrySmiteEvilFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_SMITE_GOOD) { if(ai_TrySmiteGoodFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_IMPROVED_POWER_ATTACK) { if(ai_TryImprovedPowerAttackFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_FLURRY_OF_BLOWS) { if(ai_TryFlurryOfBlowsFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_STUNNING_FIST) { if(ai_TryStunningFistFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_SAP) { if(ai_TrySapFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_DISARM) { if(ai_TryDisarmFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_KI_DAMAGE) { if(ai_TryKiDamageFeat(oCreature, oTarget)) return; }
else if(nId == FEAT_CALLED_SHOT) { if(ai_TryCalledShotFeat(oCreature, oTarget)) return; }
}
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,82 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_monk
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Monk class.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryWholenessOfBodyFeat(oCreature)) return;
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,131 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_o_cmb_modes
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates to not use any combat modes during combat ai.
OBJECT_SELF is the creature running the ai.
Our actions.
1 - Get nearest enemy.
2 - Check for healing and curing first.
3 - Check moral if wounded and this is a simple+ battle.
4 - Check for a magical ranged attack if not in melee and a difficult+ battle.
5 - Check for a buff or summons if this is a difficult+ battle.
6 - Check for a Class ability and an offensive spell if this is a simple+ battle.
7 - Check for a physical attack.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
// ******************* OFFENSIVE AOE TALENTS ***********************
// Check the battlefield for a group of enemies to shoot a big spell at!
// We are checking here since these opportunities are rare and we need
// to take advantage of them as often as possible.
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
}
if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING))
{
// ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************
// Does our master want to be buffed first?
object oTarget = OBJECT_INVALID;
if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return;
if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return;
if(ai_TryDivineMightFeat(oCreature, nInMelee)) return;
}
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TryBarbarianRageFeat(oCreature)) return;
if(ai_TryBardSongFeat(oCreature)) return;
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TrySummonFamiliarTalent(oCreature)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// ************************** CLASS FEATURES ***************************
if(ai_TryTurningTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
if(AI_DEBUG) ai_Debug("ai_a_no_modes", "78", "Check for ranged attack on weakest enemy!");
object oTarget;
int bAlwaysAtk = !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK);
// ************************** Ranged feat attacks **************************
if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) &&
!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) &&
ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
// Lets pick off the weaker targets.
if(!nInMelee)
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
if(AI_DEBUG) ai_Debug("ai_a_no_modes", "105", GetName(OBJECT_SELF) + " does ranged attack on weakest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
if(AI_DEBUG) ai_Debug("ai_a_no_modes", "117", "Check for melee attack on weakest enemy!");
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TrySneakAttack(oCreature, nInMelee, bAlwaysAtk)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_PERCEPTION, bAlwaysAtk);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee, bAlwaysAtk);
if(oTarget != OBJECT_INVALID)
{
if(AI_DEBUG) ai_Debug("ai_a_no_modes", "126", GetName(OBJECT_SELF) + " does melee attack against weakest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,110 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_paladin
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Paladin class.
Paladins always protect their masters and face the strongest opponents first!
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
// ******************* OFFENSIVE AOE TALENTS ***********************
// Check the battlefield for a group of enemies to shoot a big spell at!
// We are checking here since these opportunities are rare and we need
// to take advantage of them as often as possible.
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
}
if(!ai_GetMagicMode(oCreature, AI_MAGIC_OFFENSIVE_CASTING))
{
// ********** PROTECTION/ENHANCEMENT/SUMMON TALENTS ************
// Does our master want to be buffed first?
object oTarget = OBJECT_INVALID;
if(ai_GetMagicMode(oCreature, AI_MAGIC_BUFF_MASTER)) oTarget = GetMaster(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, 0, oTarget)) return;
if(ai_TryDivineShieldFeat(oCreature, nInMelee)) return;
if(ai_TryDivineMightFeat(oCreature, nInMelee)) return;
}
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// ************************** CLASS FEATURES ***************************
if(ai_TryTurningTalent(oCreature)) return;
if(ai_TryLayOnHands(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget = OBJECT_INVALID;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Paladins ALWAYS protect their masters first!
oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Paladins face off against the strongest opponents first.
if(!nInMelee) oTarget = ai_GetHighestCRTarget(oCreature);
else oTarget = ai_GetHighestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
// Paladins ALWAYS protect their masters first!
oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
int bCheckCombat = ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK);
if(bCheckCombat) oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee, FALSE);
// If always attacking Paladins ALWAYS attack the strongest opponent.
else oTarget = ai_GetHighestCRTargetForMeleeCombat(oCreature, nInMelee);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,81 @@
/*//////////////////////////////////////////////////////////////////////////////
Script Name: ai_a_peaceful
////////////////////////////////////////////////////////////////////////////////
ai script mode for associates to use when they should remain out of combat.
OBJECT_SELF is the creature running the ai.
////////////////////////////////////////////////////////////////////////////////
Programmer: Philos
*///////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST);
float fDistance = GetDistanceBetween(oCreature, oNearestEnemy);
// In Melee combat!
if(nInMelee > 0)
{
// If we are not being attacked then we should back out of combat.
if(ai_GetEnemyAttackingMe(oCreature) == OBJECT_INVALID)
{
if(AI_DEBUG) ai_Debug("ai_a_peaceful", "23", GetName(oCreature) + " is moving away from " + GetName(oNearestEnemy) +
"[" + FloatToString(AI_RANGE_MELEE - fDistance + 1.0, 0, 2) + "]" + " to use a ranged weapon.");
ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE);
// Lets move just out of melee range!
int bRun = ai_CanIMoveInCombat(oCreature);
ActionMoveAwayFromObject(oNearestEnemy, bRun, AI_RANGE_CLOSE + 2.0);
ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature));
return;
}
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TryImprovedExpertiseFeat(oCreature)) return;
if(ai_TryExpertiseFeat(oCreature)) return;
// Lets get the strongest melee opponent in melee with us.
object oTarget = ai_GetHighestCRTargetForMeleeCombat(oCreature, nInMelee);
if(oTarget == OBJECT_INVALID) oTarget = oNearestEnemy;
// Use knockdown when appropriate and the target is not immune.
if(ai_TryKnockdownFeat(oCreature, oTarget)) return;
if (ai_TryParry(oCreature)) return;
// We have tried everything to protect ourselves so the only thing left
// to do is man up and attack!
// Physical attacks are under TALENT_CATEGORY_HARMFUL_MELEE(22).
ai_DoPhysicalAttackOnNearest(oCreature, nInMelee);
return;
}
if(fDistance <= AI_RANGE_LONG)
{
if(AI_DEBUG) ai_Debug("ai_a_peaceful", "49", GetName(oCreature) + " is moving away from " + GetName(oNearestEnemy) +
"[" + FloatToString(AI_RANGE_LONG - fDistance, 0, 2) + "]" + ".");
ai_SetLastAction(oCreature, AI_LAST_ACTION_MOVE);
// Lets move out of close range!
ActionMoveAwayFromObject(oNearestEnemy, TRUE, AI_RANGE_LONG + 2.0);
ActionDoCommand(ExecuteScript("0e_do_combat_rnd", oCreature));
return;
}
//************************* OUT OF COMBAT **************************
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, 0, oCreature)) return;
if(ai_TryCureConditionTalent(oCreature, 0)) return;
//************************** DEFENSIVE TALENTS ***************************
// Has our master told us to not use magic?
int bUseMagic = !ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC);
if(bUseMagic)
{
// If can turn invisible then we should probably do that!
if(ai_UseTalent(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_INVISIBILITY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_INVISIBILITY_SPHERE, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_SANCTUARY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_ETHEREALNESS, oCreature)) return; // Greater Sanctuary
if(ai_UseTalent(oCreature, SPELLABILITY_AS_IMPROVED_INVISIBLITY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELLABILITY_AS_INVISIBILITY, oCreature)) return;
int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature);
// Summons are powerfull and should be used as much as possible.
if(ai_UseCreatureTalent(oCreature, AI_TALENT_SUMMON, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_PROTECTION, nInMelee, nMaxLevel)) return;
}
// Stand and watch the battle we don't want to provoke anyone!
if(AI_DEBUG) ai_Debug("ai_a_peaceful", "80", GetName(oCreature) + " is holding here.");
}

View File

@ -0,0 +1,70 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_polymorphed
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for polymorphed associates.
We check for abilities based on the form we are using and if we should polymorph back.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void ai_DoActions(object oCreature, int nForm)
{
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST);
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
if(GetPercentageHPLoss(oCreature) <= AI_HEALTH_BLOODY)
{
//ai_Debug("ai_a_polymorphed", "24", "We are wounded and are transforming back!");
ai_RemoveASpecificEffect(oCreature, EFFECT_TYPE_POLYMORPH);
return;
}
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// When polymorphed we turn back then check moral.
//if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget = ai_GetLowestCRTargetForMeleeCombat(oCreature, nInMelee);
// If we don't find a target then we don't want to fight anyone!
if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
else ai_SearchForHiddenCreature(oCreature, FALSE);
}
void main()
{
object oCreature = OBJECT_SELF;
// Need to know who we are so we can use thier abilities.
int nForm = GetAppearanceType(oCreature);
// Check to see if we are back to our normal form?(-1 to get the actual form #)
if(nForm == GetLocalInt(oCreature, AI_NORMAL_FORM) - 1)
{
// If we are transformed back then go back to our primary ai.
ai_SetCreatureAIScript(oCreature);
DeleteLocalInt(oCreature, AI_NORMAL_FORM);
string sAI = GetLocalString(oCreature, AI_COMBAT_SCRIPT);
if(sAI == "ai_a_polymorphed" || sAI == "") sAI = "ai_a_default";
ExecuteScript(sAI, oCreature);
}
else ai_DoActions(oCreature, nForm);
}

View File

@ -0,0 +1,129 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_ranged
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates to use the ranged ai.
OBJECT_SELF is the creature running the ai.
Will attempt to use ranged weapons until surrounded.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
// Turning is basically a powerful AOE so treat it like one.
if(ai_TryTurningTalent(oCreature)) return;
if(ai_TryBarbarianRageFeat(oCreature)) return;
if(ai_TryBardSongFeat(oCreature)) return;
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
if(ai_TrySummonFamiliarTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// ************************** CLASS FEATURES ***************************
if(ai_TryTurningTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED))
{
if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature) &&
nInMelee < 3)
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Lets defend master, nearest favored enemy, ranged, sneak, weakest targets.
if(!nInMelee)
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget == ai_GetRangedTarget(oCreature);
if(oTarget == OBJECT_INVALID && ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
}
// ************************** Melee feat attacks *************************
object oNearestEnemy = GetLocalObject(oCreature, AI_ENEMY_NEAREST);
if(nInMelee)
{
oTarget = ai_GetEnemyAttackingMe(oCreature);
if(oTarget != OBJECT_INVALID)
{
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TrySneakAttack(oCreature, nInMelee)) return;
if(ai_TryWhirlwindFeat(oCreature)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee);
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
return;
}
}
}
if(oNearestEnemy != OBJECT_INVALID)
{
float fDistance = GetDistanceBetween(oCreature, oNearestEnemy);
float fRange = AI_RANGE_LONG;
if(GetIsAreaInterior(GetArea(oCreature))) fRange = AI_RANGE_CLOSE;
if(GetHasFeat(FEAT_SNEAK_ATTACK, oCreature)) fRange = AI_RANGE_CLOSE;
if(fDistance < fRange)
{
int bRun = ai_CanIMoveInCombat(oCreature);
ActionMoveAwayFromObject(oNearestEnemy, bRun, fRange - fDistance + 2.0);
}
}
else ai_SearchForHiddenCreature(oCreature, FALSE, OBJECT_INVALID, AI_RANGE_CLOSE);
}

View File

@ -0,0 +1,96 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_ranger
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Ranger class.
Rangers will take out favored enemies first!
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TrySummonAnimalCompanionTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee)
{
oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
}
else
{
oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
// Our master may have setup to check difficulty before we move into melee.
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_PERCEPTION, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee);
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,83 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_rogue
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Rogue class.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
if(ai_TryRangedSneakAttack(oCreature, nInMelee)) return;
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TrySneakAttack(oCreature, nInMelee)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,75 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_sorcerer
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Sorcerer class.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,53 @@
/*//////////////////////////////////////////////////////////////////////////////
Script Name: ai_a_taunter
////////////////////////////////////////////////////////////////////////////////
ai script for creatures using defined to use the taunt skill.
OBJECT_SELF is the creature running the ai.
////////////////////////////////////////////////////////////////////////////////
Programmer: Philos
*///////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
//************************** SKILL FEATURES **************************
if(ai_TryAnimalEmpathy(oCreature)) return;
// ************************** CLASS FEATURES ***************************
if(ai_TryBarbarianRageFeat(oCreature)) return;
if(ai_TryBardSongFeat(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Class and Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
// ************************** CLASS FEATURES ***************************
if(ai_TryTurningTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// Taunt the nearest target!
if (ai_TryTaunt (oCreature, ai_GetNearestTargetForMeleeCombat (oCreature, nInMelee))) return;
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
ai_DoPhysicalAttackOnLowestCR(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
}

View File

@ -0,0 +1,77 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_a_wizard
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for associates using the Wizard class.
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
int nDifficulty = ai_GetDifficulty(oCreature);
int nMaxLevel;
// Check for moral and get the maximum spell level we should use.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(nInMelee && ai_MoralCheck(oCreature)) return;
nMaxLevel = ai_GetAssociateTalentMaxLevel(oCreature, nDifficulty);
}
// Skill, Class, Offensive AOE's, and Defensive talents.
if(nDifficulty >= AI_COMBAT_MODERATE)
{
// ************************** CLASS FEATURES ***************************
if(ai_TrySummonFamiliarTalent(oCreature)) return;
// *************************** SPELL TALENTS ***************************
if(ai_CheckForAssociateSpellTalent(oCreature, nInMelee, nMaxLevel)) return;
}
// Offensive single target talents.
if(nDifficulty >= AI_COMBAT_EFFORTLESS)
{
if(!ai_GetMagicMode(oCreature, AI_MAGIC_DEFENSIVE_CASTING))
{
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
}
}
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
object oTarget;
// ************************** Ranged feat attacks **************************
if(!ai_GetAIMode(oCreature, AI_MODE_STOP_RANGED) && ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
// Are we suppose to protect our master first?
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID)
{
// Lets pick off the weakest targets.
if(!nInMelee) oTarget = ai_GetLowestCRTarget(oCreature);
else oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, FALSE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
// ************************** Melee feat attacks *************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetBestTargetForMeleeCombat(oCreature, nInMelee, !ai_GetAIMode(oCreature, AI_MODE_CHECK_ATTACK));
if(oTarget != OBJECT_INVALID) ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
else ai_SearchForHiddenCreature(oCreature, FALSE);
}

View File

@ -0,0 +1,100 @@
/*////////////////////////////////////////////////////////////////////////////////////////////////////
// Script Name: ai_ambusher
//////////////////////////////////////////////////////////////////////////////////////////////////////
ai script for ambushing creatures (Any).
OBJECT_SELF is the creature running the ai.
*/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programmer: Philos
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
// Rule used to disable ambush if the player wants to.
if(!GetLocalInt(GetModule(), AI_RULE_AMBUSH))
{
ExecuteScript("ai_default", oCreature);
return;
}
// If can turn invisible then we should probably do that!
if(ai_UseTalent(oCreature, SPELL_IMPROVED_INVISIBILITY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_INVISIBILITY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_INVISIBILITY_SPHERE, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_SANCTUARY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELL_ETHEREALNESS, oCreature)) return; // Greater Sanctuary
if(ai_UseTalent(oCreature, SPELLABILITY_AS_IMPROVED_INVISIBLITY, oCreature)) return;
if(ai_UseTalent(oCreature, SPELLABILITY_AS_INVISIBILITY, oCreature)) return;
// Check the battle field to see if anyone see us?
int nEnemyIndex = ai_GetNearestIndexThatSeesUs(oCreature);
// If seen, can we try to hide now?
if(nEnemyIndex)
{
// Check for an attacker and can they see through invisibility?
object oAttacker = ai_GetEnemyAttackingMe(oCreature);
int bCanSeeInvisible;
if(oAttacker != OBJECT_INVALID)
{
bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_SEEINVISIBLE);
if(!bCanSeeInvisible) bCanSeeInvisible = ai_GetHasEffectType(oAttacker, EFFECT_TYPE_TRUESEEING);
if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_5_FEET, oCreature);
if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_10_FEET, oCreature);
if(!bCanSeeInvisible) bCanSeeInvisible = GetHasFeat(FEAT_BLINDSIGHT_60_FEET, oCreature);
}
if(AI_DEBUG) ai_Debug("ai_ambusher", "43", "bCanSeeInvisible: " + IntToString(bCanSeeInvisible));
if(!bCanSeeInvisible)
{
if(GetHasFeat(FEAT_HIDE_IN_PLAIN_SIGHT, oCreature))
{
if(!GetActionMode(oCreature, ACTION_MODE_STEALTH))
{
if(AI_DEBUG) ai_Debug("ai_ambusher", "50", GetName(oCreature) + " is using hide in plain sight!");
ClearAllActions(TRUE);
SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE);
return;
}
}
// Does not have hide in plain sight.
else
{
string sEnemyIndex = IntToString(nEnemyIndex);
float fEnemyDistance = GetLocalFloat(oCreature, AI_ENEMY_RANGE + sEnemyIndex);
if(AI_DEBUG) ai_Debug("ai_ambusher", "61", "fDistance: " + FloatToString(fEnemyDistance, 0, 2));
if(fEnemyDistance >= AI_RANGE_LONG)
{
int bTried = GetLocalInt(oCreature, AI_TRIED_TO_HIDE);
if(!bTried)
{
// Move away so we can hide.
if(AI_DEBUG) ai_Debug("ai_ambusher", "68", GetName(oCreature) + " is trying to move away to hide!");
SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
object oEnemy = GetLocalObject(oCreature, AI_ENEMY + sEnemyIndex);
ActionMoveAwayFromObject(oEnemy, TRUE, AI_RANGE_BATTLEFIELD);
SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3);
return;
}
else SetLocalInt(oCreature, AI_TRIED_TO_HIDE, GetLocalInt(oCreature, AI_TRIED_TO_HIDE) - 1);
}
// We have been seen by an enemy too close to us so drop stealth.
else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
}
}
// The enemy can see through stealth so lets drop it.
else SetActionMode(oCreature, ACTION_MODE_STEALTH, FALSE);
}
// We are not in stealth mode so lets get there.
else if(!GetActionMode(oCreature, ACTION_MODE_STEALTH))
{
// Use any hiding talents we have
if(AI_DEBUG) ai_Debug("ai_ambusher", "88", GetName(oCreature) + " is trying to hide!");
SetActionMode(oCreature, ACTION_MODE_STEALTH, TRUE);
SetLocalInt(oCreature, AI_TRIED_TO_HIDE, 3);
return;
}
// If we have givin up on stealth do our normal actions.
string sScript = GetLocalString(oCreature, AI_DEFAULT_SCRIPT);
if(sScript == "ai_ambusher" || sScript == "") sScript = "ai_default";
if(AI_DEBUG) ai_Debug("ai_ambusher", "96", "sScript: " + sScript + " AI_DEFAULT_SCRIPT: " + GetLocalString(oCreature, AI_DEFAULT_SCRIPT));
ExecuteScript(sScript, oCreature);
}

View File

@ -0,0 +1,71 @@
/*//////////////////////////////////////////////////////////////////////////////
Script Name: ai_barbarian
////////////////////////////////////////////////////////////////////////////////
ai script for creatures using the class Barbarian.
OBJECT_SELF is the creature running the ai.
////////////////////////////////////////////////////////////////////////////////
Programmer: Philos
*///////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
void main()
{
object oCreature = OBJECT_SELF;
// Get the number of enemies that we are in melee combat with.
int nInMelee = ai_GetNumOfEnemiesInRange(oCreature);
object oTarget;
if(!GetHasFeatEffect(FEAT_BARBARIAN_RAGE, oCreature))
{
//*************************** HEALING & CURES ****************************
if(ai_TryHealingTalent(oCreature, nInMelee)) return;
if(ai_TryCureConditionTalent(oCreature, nInMelee)) return;
if(nInMelee && ai_MoralCheck(oCreature)) return;
int nMaxLevel = ai_GetMonsterTalentMaxLevel(oCreature);
//******************* OFFENSIVE AREA OF EFFECT TALENTS *******************
// Check the battlefield for a group of enemies to shoot a big talent at!
// We are checking here since these opportunities are rare and we need
// to take advantage of them as often as possible.
if(ai_UseCreatureTalent(oCreature, AI_TALENT_INDISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_DISCRIMINANT_AOE, nInMelee, nMaxLevel)) return;
//**************************** CLASS FEATURES ****************************
if(ai_TryBarbarianRageFeat(oCreature)) return;
//************************** DEFENSIVE TALENTS ***************************
int nRound = ai_GetCurrentRound(oCreature);
if(ai_TryDefensiveTalents(oCreature, nInMelee, nMaxLevel, nRound)) return;
//********************** OFFENSIVE TARGETED TALENTS **********************
// Look for a touch attack since we are in melee.
if(nInMelee > 0 && ai_UseCreatureTalent(oCreature, AI_TALENT_TOUCH, nInMelee, nMaxLevel)) return;
if(ai_UseCreatureTalent(oCreature, AI_TALENT_RANGED, nInMelee, nMaxLevel)) return;
// PHYSICAL ATTACKS - Either we don't have talents or we are saving them.
// *************************** RANGED ATTACKS *****************************
if(ai_CanIUseRangedWeapon(oCreature, nInMelee))
{
if(ai_HasRangedWeaponWithAmmo(oCreature))
{
if(!nInMelee) oTarget = ai_GetNearestTarget(oCreature);
else oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
}
else
{
ai_SearchForHiddenCreature(oCreature, TRUE);
return;
}
}
else if(ai_InCombatEquipBestRangedWeapon(oCreature)) return;
}
}
// ***************************** MELEE ATTACKS ***************************
if(ai_InCombatEquipBestMeleeWeapon(oCreature)) return;
if(ai_TryWhirlwindFeat(oCreature)) return;
oTarget = ai_GetNearestTargetForMeleeCombat(oCreature, nInMelee);
if(oTarget != OBJECT_INVALID)
{
if(ai_TryMeleeTalents(oCreature, oTarget)) return;
ai_ActionAttack(oCreature, AI_LAST_ACTION_MELEE_ATK, oTarget);
}
else ai_SearchForHiddenCreature(oCreature, TRUE);
}

Some files were not shown because too many files have changed in this diff Show More