generated from Jaysyn/ModuleTemplate
2025/07/19 Update
Added PEPS. Full compile.
This commit is contained in:
parent
e518db42dc
commit
352e9f3ee2
12
nasher.cfg
12
nasher.cfg
@ -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
1
pack_haks.cmd
Normal file
@ -0,0 +1 @@
|
||||
nasher pack pepshak --verbose
|
49
src/hakpak/peps_prc8/2da/ai_messages.2da
Normal file
49
src/hakpak/peps_prc8/2da/ai_messages.2da
Normal 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!"
|
19400
src/hakpak/peps_prc8/2da/ai_spells.2da
Normal file
19400
src/hakpak/peps_prc8/2da/ai_spells.2da
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/hakpak/peps_prc8/tga/armor_pallet.tga
Normal file
BIN
src/hakpak/peps_prc8/tga/armor_pallet.tga
Normal file
Binary file not shown.
After Width: | Height: | Size: 176 KiB |
BIN
src/hakpak/peps_prc8/tga/gui_pal_tattoo.tga
Normal file
BIN
src/hakpak/peps_prc8/tga/gui_pal_tattoo.tga
Normal file
Binary file not shown.
After Width: | Height: | Size: 176 KiB |
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
49670
src/module/dlg/nw_g_animal.dlg.json
Normal file
49670
src/module/dlg/nw_g_animal.dlg.json
Normal file
File diff suppressed because it is too large
Load Diff
23412
src/module/dlg/nw_g_fam.dlg.json
Normal file
23412
src/module/dlg/nw_g_fam.dlg.json
Normal file
File diff suppressed because it is too large
Load Diff
27180
src/module/dlg/oc_ai_henchmen.dlg.json
Normal file
27180
src/module/dlg/oc_ai_henchmen.dlg.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -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": {
|
||||
|
172
src/module/nss/0c_assoc_actions.nss
Normal file
172
src/module/nss/0c_assoc_actions.nss
Normal 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);
|
||||
}
|
18
src/module/nss/0c_cast_polymorp.nss
Normal file
18
src/module/nss/0c_cast_polymorp.nss
Normal 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);
|
||||
}
|
||||
|
15
src/module/nss/0c_fire_henchmen.nss
Normal file
15
src/module/nss/0c_fire_henchmen.nss
Normal 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);
|
||||
}
|
||||
|
22
src/module/nss/0c_get_convo.nss
Normal file
22
src/module/nss/0c_get_convo.nss
Normal 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()));
|
||||
}
|
25
src/module/nss/0c_get_henchman.nss
Normal file
25
src/module/nss/0c_get_henchman.nss
Normal 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);
|
||||
}
|
||||
|
||||
|
12
src/module/nss/0c_h_cast_spell.nss
Normal file
12
src/module/nss/0c_h_cast_spell.nss
Normal 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")));
|
||||
}
|
81
src/module/nss/0c_henchmenspell.nss
Normal file
81
src/module/nss/0c_henchmenspell.nss
Normal 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;
|
||||
}
|
16
src/module/nss/0c_if_a_magic_m.nss
Normal file
16
src/module/nss/0c_if_a_magic_m.nss
Normal 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);
|
||||
}
|
132
src/module/nss/0c_if_ass_convo.nss
Normal file
132
src/module/nss/0c_if_ass_convo.nss
Normal 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;
|
||||
}
|
22
src/module/nss/0c_if_assoc_mode.nss
Normal file
22
src/module/nss/0c_if_assoc_mode.nss
Normal 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);
|
||||
}
|
17
src/module/nss/0c_if_cntrspell.nss
Normal file
17
src/module/nss/0c_if_cntrspell.nss
Normal 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");
|
||||
}
|
16
src/module/nss/0c_if_com_script.nss
Normal file
16
src/module/nss/0c_if_com_script.nss
Normal 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);
|
||||
}
|
21
src/module/nss/0c_if_convo.nss
Normal file
21
src/module/nss/0c_if_convo.nss
Normal 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;
|
||||
}
|
18
src/module/nss/0c_if_has_assoc.nss
Normal file
18
src/module/nss/0c_if_has_assoc.nss
Normal 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);
|
||||
}
|
28
src/module/nss/0c_if_has_class.nss
Normal file
28
src/module/nss/0c_if_has_class.nss
Normal 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;
|
||||
}
|
22
src/module/nss/0c_if_has_feat.nss
Normal file
22
src/module/nss/0c_if_has_feat.nss
Normal 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));
|
||||
}
|
26
src/module/nss/0c_if_has_spell.nss
Normal file
26
src/module/nss/0c_if_has_spell.nss
Normal 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;
|
||||
}
|
12
src/module/nss/0c_if_hen_leave.nss
Normal file
12
src/module/nss/0c_if_hen_leave.nss
Normal 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;
|
||||
}
|
17
src/module/nss/0c_if_identify.nss
Normal file
17
src/module/nss/0c_if_identify.nss
Normal 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);
|
||||
}
|
11
src/module/nss/0c_if_not_master.nss
Normal file
11
src/module/nss/0c_if_not_master.nss
Normal 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());
|
||||
}
|
13
src/module/nss/0c_if_open_inven.nss
Normal file
13
src/module/nss/0c_if_open_inven.nss
Normal 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;
|
||||
}
|
12
src/module/nss/0c_if_pickuploot.nss
Normal file
12
src/module/nss/0c_if_pickuploot.nss
Normal 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;
|
||||
}
|
11
src/module/nss/0c_if_polymorph.nss
Normal file
11
src/module/nss/0c_if_polymorph.nss
Normal 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;
|
||||
}
|
11
src/module/nss/0c_if_scout.nss
Normal file
11
src/module/nss/0c_if_scout.nss
Normal 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;
|
||||
}
|
18
src/module/nss/0c_if_skillrank.nss
Normal file
18
src/module/nss/0c_if_skillrank.nss
Normal 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);
|
||||
}
|
15
src/module/nss/0c_if_taunt.nss
Normal file
15
src/module/nss/0c_if_taunt.nss
Normal 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");
|
||||
}
|
19
src/module/nss/0c_listhenchman.nss
Normal file
19
src/module/nss/0c_listhenchman.nss
Normal 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);
|
||||
}
|
||||
}
|
27
src/module/nss/0c_no_com_script.nss
Normal file
27
src/module/nss/0c_no_com_script.nss
Normal 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);
|
||||
}
|
14
src/module/nss/0c_remove_effect.nss
Normal file
14
src/module/nss/0c_remove_effect.nss
Normal 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);
|
||||
}
|
||||
|
17
src/module/nss/0c_summon_assoc.nss
Normal file
17
src/module/nss/0c_summon_assoc.nss
Normal 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 ();
|
||||
}
|
15
src/module/nss/0c_use_feat.nss
Normal file
15
src/module/nss/0c_use_feat.nss
Normal 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);
|
||||
}
|
16
src/module/nss/0e_c2_1_hb.nss
Normal file
16
src/module/nss/0e_c2_1_hb.nss
Normal 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");
|
||||
}
|
32
src/module/nss/0e_c2_7_ondeath.nss
Normal file
32
src/module/nss/0e_c2_7_ondeath.nss
Normal 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"));
|
||||
}
|
||||
|
14
src/module/nss/0e_ch_1_hb.nss
Normal file
14
src/module/nss/0e_ch_1_hb.nss
Normal 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");
|
||||
}
|
41
src/module/nss/0e_ch_7_ondeath.nss
Normal file
41
src/module/nss/0e_ch_7_ondeath.nss
Normal 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"));
|
||||
}
|
||||
|
22
src/module/nss/0e_do_combat_rnd.nss
Normal file
22
src/module/nss/0e_do_combat_rnd.nss
Normal 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);
|
||||
}
|
||||
}
|
60
src/module/nss/0e_gui_events.nss
Normal file
60
src/module/nss/0e_gui_events.nss
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
46
src/module/nss/0e_m1_3_endround.nss
Normal file
46
src/module/nss/0e_m1_3_endround.nss
Normal 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
1975
src/module/nss/0e_nui.nss
Normal file
File diff suppressed because it is too large
Load Diff
700
src/module/nss/0e_nui_dm.nss
Normal file
700
src/module/nss/0e_nui_dm.nss
Normal 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));
|
||||
}
|
23
src/module/nss/0e_onclientload.nss
Normal file
23
src/module/nss/0e_onclientload.nss
Normal 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);
|
||||
}
|
||||
}
|
154
src/module/nss/0e_player_target.nss
Normal file
154
src/module/nss/0e_player_target.nss
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
78
src/module/nss/0e_prc_ch_events.nss
Normal file
78
src/module/nss/0e_prc_ch_events.nss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
2325
src/module/nss/0i_actions.nss
Normal file
2325
src/module/nss/0i_actions.nss
Normal file
File diff suppressed because it is too large
Load Diff
2192
src/module/nss/0i_associates.nss
Normal file
2192
src/module/nss/0i_associates.nss
Normal file
File diff suppressed because it is too large
Load Diff
70
src/module/nss/0i_color.nss
Normal file
70
src/module/nss/0i_color.nss
Normal 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
3498
src/module/nss/0i_combat.nss
Normal file
File diff suppressed because it is too large
Load Diff
667
src/module/nss/0i_constants.nss
Normal file
667
src/module/nss/0i_constants.nss
Normal 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;
|
1032
src/module/nss/0i_gui_events.nss
Normal file
1032
src/module/nss/0i_gui_events.nss
Normal file
File diff suppressed because it is too large
Load Diff
1243
src/module/nss/0i_items.nss
Normal file
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
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
4823
src/module/nss/0i_menus.nss
Normal file
File diff suppressed because it is too large
Load Diff
1386
src/module/nss/0i_menus_dm.nss
Normal file
1386
src/module/nss/0i_menus_dm.nss
Normal file
File diff suppressed because it is too large
Load Diff
88
src/module/nss/0i_messages.nss
Normal file
88
src/module/nss/0i_messages.nss
Normal 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);
|
||||
}
|
544
src/module/nss/0i_module.nss
Normal file
544
src/module/nss/0i_module.nss
Normal 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
434
src/module/nss/0i_nui.nss
Normal 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;
|
||||
}
|
||||
|
793
src/module/nss/0i_player_target.nss
Normal file
793
src/module/nss/0i_player_target.nss
Normal 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
2157
src/module/nss/0i_spells.nss
Normal file
File diff suppressed because it is too large
Load Diff
423
src/module/nss/0i_states_cond.nss
Normal file
423
src/module/nss/0i_states_cond.nss
Normal 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);
|
||||
}
|
||||
|
3098
src/module/nss/0i_talents.nss
Normal file
3098
src/module/nss/0i_talents.nss
Normal file
File diff suppressed because it is too large
Load Diff
95
src/module/nss/0i_time.nss
Normal file
95
src/module/nss/0i_time.nss
Normal 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");
|
||||
}
|
105
src/module/nss/ai_a_ambusher.nss
Normal file
105
src/module/nss/ai_a_ambusher.nss
Normal 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);
|
||||
}
|
159
src/module/nss/ai_a_atk_casters.nss
Normal file
159
src/module/nss/ai_a_atk_casters.nss
Normal 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);
|
||||
}
|
||||
|
80
src/module/nss/ai_a_atk_nearest.nss
Normal file
80
src/module/nss/ai_a_atk_nearest.nss
Normal 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));
|
||||
}
|
||||
|
159
src/module/nss/ai_a_atk_warrior.nss
Normal file
159
src/module/nss/ai_a_atk_warrior.nss
Normal 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);
|
||||
}
|
||||
|
87
src/module/nss/ai_a_barbarian.nss
Normal file
87
src/module/nss/ai_a_barbarian.nss
Normal 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);
|
||||
}
|
83
src/module/nss/ai_a_bard.nss
Normal file
83
src/module/nss/ai_a_bard.nss
Normal 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);
|
||||
}
|
102
src/module/nss/ai_a_cleric.nss
Normal file
102
src/module/nss/ai_a_cleric.nss
Normal 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);
|
||||
}
|
69
src/module/nss/ai_a_cntrspell.nss
Normal file
69
src/module/nss/ai_a_cntrspell.nss
Normal 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");
|
||||
}
|
80
src/module/nss/ai_a_default.nss
Normal file
80
src/module/nss/ai_a_default.nss
Normal 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));
|
||||
}
|
||||
|
77
src/module/nss/ai_a_defensive.nss
Normal file
77
src/module/nss/ai_a_defensive.nss
Normal 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));
|
||||
}
|
86
src/module/nss/ai_a_druid.nss
Normal file
86
src/module/nss/ai_a_druid.nss
Normal 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);
|
||||
}
|
82
src/module/nss/ai_a_fighter.nss
Normal file
82
src/module/nss/ai_a_fighter.nss
Normal 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);
|
||||
}
|
117
src/module/nss/ai_a_flanker.nss
Normal file
117
src/module/nss/ai_a_flanker.nss
Normal 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);
|
||||
}
|
123
src/module/nss/ai_a_invisible.nss
Normal file
123
src/module/nss/ai_a_invisible.nss
Normal 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);
|
||||
}
|
||||
|
82
src/module/nss/ai_a_monk.nss
Normal file
82
src/module/nss/ai_a_monk.nss
Normal 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);
|
||||
}
|
131
src/module/nss/ai_a_no_cmb_mode.nss
Normal file
131
src/module/nss/ai_a_no_cmb_mode.nss
Normal 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);
|
||||
}
|
||||
|
110
src/module/nss/ai_a_paladin.nss
Normal file
110
src/module/nss/ai_a_paladin.nss
Normal 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);
|
||||
}
|
81
src/module/nss/ai_a_peaceful.nss
Normal file
81
src/module/nss/ai_a_peaceful.nss
Normal 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.");
|
||||
}
|
70
src/module/nss/ai_a_polymorphed.nss
Normal file
70
src/module/nss/ai_a_polymorphed.nss
Normal 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);
|
||||
}
|
129
src/module/nss/ai_a_ranged.nss
Normal file
129
src/module/nss/ai_a_ranged.nss
Normal 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);
|
||||
}
|
||||
|
96
src/module/nss/ai_a_ranger.nss
Normal file
96
src/module/nss/ai_a_ranger.nss
Normal 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);
|
||||
}
|
83
src/module/nss/ai_a_rogue.nss
Normal file
83
src/module/nss/ai_a_rogue.nss
Normal 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);
|
||||
}
|
75
src/module/nss/ai_a_sorcerer.nss
Normal file
75
src/module/nss/ai_a_sorcerer.nss
Normal 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);
|
||||
}
|
53
src/module/nss/ai_a_taunter.nss
Normal file
53
src/module/nss/ai_a_taunter.nss
Normal 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));
|
||||
}
|
77
src/module/nss/ai_a_wizard.nss
Normal file
77
src/module/nss/ai_a_wizard.nss
Normal 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);
|
||||
}
|
100
src/module/nss/ai_ambusher.nss
Normal file
100
src/module/nss/ai_ambusher.nss
Normal 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);
|
||||
}
|
71
src/module/nss/ai_barbarian.nss
Normal file
71
src/module/nss/ai_barbarian.nss
Normal 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
Loading…
x
Reference in New Issue
Block a user